merge build and package command
This commit is contained in:
parent
cc6cf18406
commit
0284eccfcd
|
@ -14,9 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Subcommand `build` to build a project
|
- Subcommand `build` to build a project
|
||||||
- Compiles the project to a datapack directory
|
- Compiles the project to a datapack directory
|
||||||
- Allows changing the output directory and setting a assets 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 `clean` to clean the output directory
|
||||||
|
- Subcommand `watch` to watch for changes and run a command
|
||||||
- Subcommand `lang-debug` to debug the language parser
|
- Subcommand `lang-debug` to debug the language parser
|
||||||
- Allows to print the parsed tokens, AST and shulkerbox datapack representation
|
- Allows to print the parsed tokens, AST and shulkerbox datapack representation
|
||||||
|
|
||||||
|
|
14
README.md
14
README.md
|
@ -28,7 +28,9 @@ shulkerscript build [OPTIONS] [PATH]
|
||||||
Where [PATH] is the path of the project folder to build [default: `.`]
|
Where [PATH] is the path of the project folder to build [default: `.`]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
- `--assets <ASSETS>` The path to the assets directory [default: `./assets`]
|
||||||
- `--output <OUTPUT>` The output directory, overrides the `DATAPACK_DIR` environment variable
|
- `--output <OUTPUT>` The output directory, overrides the `DATAPACK_DIR` environment variable
|
||||||
|
- `--zip` Package the output into a zip file
|
||||||
|
|
||||||
Environment variables:
|
Environment variables:
|
||||||
- `DATAPACK_DIR` The output directory [default: `./dist`]
|
- `DATAPACK_DIR` The output directory [default: `./dist`]
|
||||||
|
@ -45,18 +47,6 @@ Options:
|
||||||
Environment variables:
|
Environment variables:
|
||||||
- `DATAPACK_DIR` The output directory [default: `./dist`]
|
- `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
|
### Watch for changes
|
||||||
```bash
|
```bash
|
||||||
shulkerscript watch [OPTIONS] [SUBCOMMAND]
|
shulkerscript watch [OPTIONS] [SUBCOMMAND]
|
||||||
|
|
|
@ -21,9 +21,6 @@ pub enum Command {
|
||||||
/// Clean build artifacts.
|
/// Clean build artifacts.
|
||||||
/// This will remove the `dist` directory.
|
/// This will remove the `dist` directory.
|
||||||
Clean(CleanArgs),
|
Clean(CleanArgs),
|
||||||
#[cfg(feature = "zip")]
|
|
||||||
/// Build and package the project.
|
|
||||||
Package(subcommands::PackageArgs),
|
|
||||||
#[cfg(feature = "watch")]
|
#[cfg(feature = "watch")]
|
||||||
/// Watch for changes and execute command.
|
/// Watch for changes and execute command.
|
||||||
Watch(subcommands::WatchArgs),
|
Watch(subcommands::WatchArgs),
|
||||||
|
@ -44,8 +41,6 @@ impl Command {
|
||||||
Command::Init(args) => subcommands::init(verbose, args)?,
|
Command::Init(args) => subcommands::init(verbose, args)?,
|
||||||
Command::Build(args) => subcommands::build(verbose, args)?,
|
Command::Build(args) => subcommands::build(verbose, args)?,
|
||||||
Command::Clean(args) => subcommands::clean(verbose, args)?,
|
Command::Clean(args) => subcommands::clean(verbose, args)?,
|
||||||
#[cfg(feature = "zip")]
|
|
||||||
Command::Package(args) => subcommands::package(verbose, args)?,
|
|
||||||
#[cfg(feature = "watch")]
|
#[cfg(feature = "watch")]
|
||||||
Command::Watch(args) => subcommands::watch(verbose, args)?,
|
Command::Watch(args) => subcommands::watch(verbose, args)?,
|
||||||
#[cfg(feature = "lang-debug")]
|
#[cfg(feature = "lang-debug")]
|
||||||
|
|
|
@ -11,6 +11,8 @@ pub enum Error {
|
||||||
NotDirectoryError(PathBuf),
|
NotDirectoryError(PathBuf),
|
||||||
#[error("An error occured because the path is neither a pack directory or a pack.toml file.")]
|
#[error("An error occured because the path is neither a pack directory or a pack.toml file.")]
|
||||||
InvalidPackPathError(PathBuf),
|
InvalidPackPathError(PathBuf),
|
||||||
|
#[error("An error occured because the feature {0} is not enabled.")]
|
||||||
|
FeatureNotEnabledError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::{Report, Result};
|
||||||
use path_absolutize::Absolutize;
|
use path_absolutize::Absolutize;
|
||||||
use shulkerbox::virtual_fs::{VFile, VFolder};
|
use shulkerbox::virtual_fs::{VFile, VFolder};
|
||||||
|
|
||||||
|
@ -25,9 +25,30 @@ pub struct BuildArgs {
|
||||||
/// Overrides the `assets` field in the pack.toml file.
|
/// Overrides the `assets` field in the pack.toml file.
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub assets: Option<PathBuf>,
|
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<()> {
|
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 path = args.path.as_path();
|
||||||
let dist_path = args
|
let dist_path = args
|
||||||
.output
|
.output
|
||||||
|
@ -35,8 +56,10 @@ 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"));
|
||||||
|
|
||||||
|
let and_package_msg = if args.zip { " and packaging" } else { "" };
|
||||||
|
|
||||||
print_info(format!(
|
print_info(format!(
|
||||||
"Building project at {}",
|
"Building{and_package_msg} project at {}",
|
||||||
path.absolutize()?.display()
|
path.absolutize()?.display()
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -87,12 +110,22 @@ pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> {
|
||||||
compiled
|
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)?;
|
output.place(&dist_path)?;
|
||||||
|
|
||||||
print_info(format!(
|
print_info(format!(
|
||||||
"Finished building project to {}",
|
"Finished building{and_package_msg} project to {}",
|
||||||
dist_path.absolutize_from(path)?.display()
|
dist_path.absolutize_from(path)?.display()
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,6 @@ pub use build::{build, BuildArgs};
|
||||||
mod clean;
|
mod clean;
|
||||||
pub use clean::{clean, CleanArgs};
|
pub use clean::{clean, CleanArgs};
|
||||||
|
|
||||||
#[cfg(feature = "zip")]
|
|
||||||
mod package;
|
|
||||||
#[cfg(feature = "zip")]
|
|
||||||
pub use package::{package, PackageArgs};
|
|
||||||
|
|
||||||
#[cfg(feature = "watch")]
|
#[cfg(feature = "watch")]
|
||||||
mod watch;
|
mod watch;
|
||||||
#[cfg(feature = "watch")]
|
#[cfg(feature = "watch")]
|
||||||
|
|
|
@ -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(())
|
|
||||||
}
|
|
|
@ -1,8 +1,4 @@
|
||||||
use std::{
|
use std::{path::Path, thread, time::Duration};
|
||||||
path::{Path, PathBuf},
|
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
use notify_debouncer_mini::{new_debouncer, notify::*, DebounceEventResult};
|
use notify_debouncer_mini::{new_debouncer, notify::*, DebounceEventResult};
|
||||||
|
@ -31,34 +27,25 @@ pub struct WatchArgs {
|
||||||
pub enum WatchSubcommand {
|
pub enum WatchSubcommand {
|
||||||
/// Build the project.
|
/// Build the project.
|
||||||
Build(BuildArgs),
|
Build(BuildArgs),
|
||||||
#[cfg(feature = "zip")]
|
|
||||||
/// Build and package the project.
|
|
||||||
Package(super::PackageArgs),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<WatchSubcommand> for Command {
|
impl From<WatchSubcommand> for Command {
|
||||||
fn from(value: WatchSubcommand) -> Self {
|
fn from(value: WatchSubcommand) -> Self {
|
||||||
match value {
|
match value {
|
||||||
WatchSubcommand::Build(args) => Command::Build(args),
|
WatchSubcommand::Build(args) => Command::Build(args),
|
||||||
#[cfg(feature = "zip")]
|
|
||||||
WatchSubcommand::Package(args) => Command::Package(args),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn watch(verbose: bool, args: &WatchArgs) -> Result<()> {
|
pub fn watch(verbose: bool, args: &WatchArgs) -> Result<()> {
|
||||||
let cmd = Command::from(args.cmd.to_owned().unwrap_or_else(|| {
|
let cmd = Command::from(
|
||||||
WatchSubcommand::Build(BuildArgs {
|
args.cmd
|
||||||
path: PathBuf::from("."),
|
.to_owned()
|
||||||
output: None,
|
.unwrap_or_else(|| WatchSubcommand::Build(BuildArgs::default())),
|
||||||
assets: None,
|
);
|
||||||
})
|
|
||||||
}));
|
|
||||||
|
|
||||||
let project_path = match &args.cmd {
|
let project_path = match &args.cmd {
|
||||||
Some(WatchSubcommand::Build(args)) => args.path.as_path(),
|
Some(WatchSubcommand::Build(args)) => args.path.as_path(),
|
||||||
#[cfg(feature = "zip")]
|
|
||||||
Some(WatchSubcommand::Package(args)) => args.build_args.path.as_path(),
|
|
||||||
None => Path::new("."),
|
None => Path::new("."),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue