update build and package commands

to use output argument or environment variable
This commit is contained in:
Moritz Hölting 2024-06-10 09:30:01 +02:00
parent 0528501f07
commit 825e1e5a29
4 changed files with 158 additions and 85 deletions

View File

@ -4,7 +4,7 @@ This is a cli tool for the shulkerscript language. It can be used to initialize
## Installation
```bash
cargo install --git https://github.com/moritz-hoelting/shulkerscript
cargo install --git https://github.com/moritz-hoelting/shulkerscript-cli
```
## Usage
@ -13,10 +13,55 @@ cargo install --git https://github.com/moritz-hoelting/shulkerscript
```bash
shulkerscript init [OPTIONS] [PATH]
```
Where [PATH] is the path of the folder to initialize in [default: .]
Where [PATH] is the path of the folder to initialize in [default: `.`]
Options:
- `--name <NAME>` The name of the project
- `--description <DESCRIPTION>` The description of the project
- `--pack-format <PACK_FORMAT>` The pack format version
- `--force` Force initialization even if the directory is not empty
### Build a project
```bash
shulkerscript build [OPTIONS] [PATH]
```
Where [PATH] is the path of the project folder to build [default: `.`]
Options:
- `--output <OUTPUT>` The output directory, overrides the `DATAPACK_DIR` environment variable
Environment variables:
- `DATAPACK_DIR` The output directory [default: `./dist`]
### Clean the output directory
```bash
shulkerscript clean [OPTIONS] [PATH]
```
Where [PATH] is the path of the project folder to clean [default: `.`]
Options:
- `--output <OUTPUT>` The output directory, overrides the `DATAPACK_DIR` environment variable
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`]
## Contributing
Pull requests are welcome. For major changes, please open an issue first
to discuss what you would like to change.
Please make sure to update tests as appropriate.
**Note that this repository only contains the cli tool for interfacing with the language. The language itself is located in the [shulkerscript-lang](https://github.com/moritz-hoelting/shulkerscript-lang) repository. Please indicate if pull requests for this repository require pull requests for the language repository**

View File

@ -16,46 +16,31 @@ pub struct BuildArgs {
/// The path of the project to build.
#[clap(default_value = ".")]
pub path: PathBuf,
/// The path of the directory to place the compiled datapack.
#[clap(short, long)]
pub output: Option<PathBuf>,
}
pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> {
let path = args.path.as_path();
let dist_path = args
.output
.clone()
.or_else(|| env::var("DATAPACK_DIR").ok().map(PathBuf::from))
.unwrap_or_else(|| path.join("dist"));
print_info(&format!(
"Building project at {}",
path.absolutize()?.display()
));
let toml_path = if !path.exists() {
print_error("The specified path does not exist.");
return Err(Error::PathNotFoundError(path.to_path_buf()))?;
} else if path.is_dir() {
let toml_path = path.join("pack.toml");
if !toml_path.exists() {
print_error("The specified directory does not contain a pack.toml file.");
Err(Error::InvalidPackPathError(path.to_path_buf()))?;
}
toml_path
} else if path.is_file()
&& path
.file_name()
.ok_or(Error::InvalidPackPathError(path.to_path_buf()))?
== "pack.toml"
{
path.to_path_buf()
} else {
print_error("The specified path is neither a directory nor a pack.toml file.");
return Err(Error::InvalidPackPathError(path.to_path_buf()))?;
};
// env::set_current_dir(
// toml_path
// .parent()
// .expect("Failed to get parent directory of pack.toml"),
// )?;
env::set_current_dir(
toml_path
.parent()
.expect("Failed to get parent directory of pack.toml"),
)?;
let toml_content = fs::read_to_string(&toml_path)?;
let project_config = toml::from_str::<ProjectConfig>(&toml_content)?;
let (project_config, toml_path) = get_pack_config(path)?;
let script_paths = get_script_paths(
&toml_path
@ -66,11 +51,7 @@ pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> {
let compiled = shulkerscript_lang::compile(&script_paths)?;
let dist_path = toml_path
.parent()
.expect("Failed to get parent directory of pack.toml")
.join("dist")
.join(project_config.pack.name);
let dist_path = dist_path.join(project_config.pack.name);
compiled.place(&dist_path)?;
@ -123,3 +104,37 @@ fn _get_script_paths(path: &Path, prefix: &str) -> std::io::Result<Vec<(String,
Ok(Vec::new())
}
}
/// Get the pack config and config path from a project path.
///
/// # Errors
/// - If the specified path does not exist.
/// - If the specified directory does not contain a pack.toml file.
pub(super) fn get_pack_config(path: &Path) -> Result<(ProjectConfig, PathBuf)> {
let toml_path = if !path.exists() {
print_error("The specified path does not exist.");
return Err(Error::PathNotFoundError(path.to_path_buf()))?;
} else if path.is_dir() {
let toml_path = path.join("pack.toml");
if !toml_path.exists() {
print_error("The specified directory does not contain a pack.toml file.");
Err(Error::InvalidPackPathError(path.to_path_buf()))?;
}
toml_path
} else if path.is_file()
&& path
.file_name()
.ok_or(Error::InvalidPackPathError(path.to_path_buf()))?
== "pack.toml"
{
path.to_path_buf()
} else {
print_error("The specified path is neither a directory nor a pack.toml file.");
return Err(Error::InvalidPackPathError(path.to_path_buf()))?;
};
let toml_content = fs::read_to_string(&toml_path)?;
let project_config = toml::from_str::<ProjectConfig>(&toml_content)?;
Ok((project_config, toml_path))
}

View File

@ -1,40 +1,78 @@
use std::path::PathBuf;
use std::{env, path::PathBuf};
use color_eyre::eyre::Result;
use path_absolutize::Absolutize;
use crate::{
error::Error,
terminal_output::{print_error, print_info},
};
use crate::terminal_output::{print_error, print_info, print_success};
#[derive(Debug, clap::Args, Clone)]
pub struct CleanArgs {
/// The path of the project to clean.
#[clap(default_value = ".")]
pub path: PathBuf,
/// The path of the directory where the compiled datapacks are placed.
#[clap(short, long)]
pub output: Option<PathBuf>,
/// Clean the whole output folder
#[clap(short, long)]
pub all: bool,
/// Force clean
#[clap(short, long)]
pub force: bool,
}
pub fn clean(_verbose: bool, args: &CleanArgs) -> Result<()> {
pub fn clean(verbose: bool, args: &CleanArgs) -> Result<()> {
let path = args.path.as_path();
let dist_path = args
.output
.clone()
.or_else(|| env::var("DATAPACK_DIR").ok().map(PathBuf::from))
.unwrap_or_else(|| path.join("dist"));
let mut delete_paths = Vec::new();
let (project_config, _) = super::build::get_pack_config(path)?;
if args.all {
if args.force {
delete_paths.push(dist_path.clone());
} else {
print_error("You must use the --force flag to clean the whole output folder.")
}
} else {
delete_paths.push(dist_path.join(&project_config.pack.name));
delete_paths.push(dist_path.join(project_config.pack.name + ".zip"));
}
print_info(&format!(
"Cleaning project at {}",
path.absolutize_from(path)?.display()
));
let dist_path = path.join("dist");
if !path.join("pack.toml").exists() {
print_error("The specified directory is not a ShulkerScript project.");
return Err(Error::InvalidPackPathError(path.to_path_buf()).into());
for delete_path in delete_paths {
if delete_path.exists() {
if verbose {
print_info(&format!("Deleting {:?}", delete_path));
}
if delete_path.is_file() {
std::fs::remove_file(&delete_path)?;
} else {
std::fs::remove_dir_all(&delete_path)?;
}
}
}
if dist_path.exists() {
std::fs::remove_dir_all(&dist_path)?;
if dist_path.is_dir()
&& dist_path.file_name().is_some_and(|s| s != "datapacks")
&& dist_path.read_dir()?.next().is_none()
{
if verbose {
print_info(&format!("Deleting {:?}, as it is empty", dist_path));
}
std::fs::remove_dir(&dist_path)?;
}
print_info("Project cleaned successfully.");
print_success("Project cleaned successfully.");
Ok(())
}

View File

@ -1,13 +1,9 @@
use std::fs;
use std::{env, path::PathBuf};
use color_eyre::eyre::Result;
use path_absolutize::Absolutize;
use crate::{
config::ProjectConfig,
error::Error,
terminal_output::{print_error, print_info},
};
use crate::{error::Error, terminal_output::print_info};
use super::BuildArgs;
@ -19,36 +15,19 @@ pub struct PackageArgs {
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 toml_path = if !path.exists() {
print_error("The specified path does not exist.");
return Err(Error::PathNotFoundError(path.to_path_buf()))?;
} else if path.is_dir() {
let toml_path = path.join("pack.toml");
if !toml_path.exists() {
print_error("The specified directory does not contain a pack.toml file.");
Err(Error::InvalidPackPathError(path.to_path_buf()))?;
}
toml_path
} else if path.is_file()
&& path
.file_name()
.ok_or(Error::InvalidPackPathError(path.to_path_buf()))?
== "pack.toml"
{
path.to_path_buf()
} else {
print_error("The specified path is neither a directory nor a pack.toml file.");
return Err(Error::InvalidPackPathError(path.to_path_buf()))?;
};
let toml_content = fs::read_to_string(&toml_path)?;
let project_config = toml::from_str::<ProjectConfig>(&toml_content)?;
let (project_config, toml_path) = super::build::get_pack_config(path)?;
let script_paths = super::build::get_script_paths(
&toml_path
@ -59,11 +38,7 @@ pub fn package(_verbose: bool, args: &PackageArgs) -> Result<()> {
let compiled = shulkerscript_lang::compile(&script_paths)?;
let dist_path = toml_path
.parent()
.expect("Failed to get parent directory of pack.toml")
.join("dist")
.join(project_config.pack.name + ".zip");
let dist_path = dist_path.join(project_config.pack.name + ".zip");
compiled.zip(&dist_path)?;