From 825e1e5a291624e6436cf13f02771458abc512c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20H=C3=B6lting?= <87192362+moritz-hoelting@users.noreply.github.com> Date: Mon, 10 Jun 2024 09:30:01 +0200 Subject: [PATCH] update build and package commands to use output argument or environment variable --- README.md | 49 +++++++++++++++++++++- src/subcommands/build.rs | 83 ++++++++++++++++++++++---------------- src/subcommands/clean.rs | 66 +++++++++++++++++++++++------- src/subcommands/package.rs | 45 +++++---------------- 4 files changed, 158 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index bccef49..c301648 100644 --- a/README.md +++ b/README.md @@ -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 ` The name of the project - `--description ` The description of the project - `--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 ` 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 ` 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 ` 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** \ No newline at end of file diff --git a/src/subcommands/build.rs b/src/subcommands/build.rs index 746268a..bbaf634 100644 --- a/src/subcommands/build.rs +++ b/src/subcommands/build.rs @@ -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, } 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::(&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 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::(&toml_content)?; + + Ok((project_config, toml_path)) +} diff --git a/src/subcommands/clean.rs b/src/subcommands/clean.rs index 44d7f3c..2590ff5 100644 --- a/src/subcommands/clean.rs +++ b/src/subcommands/clean.rs @@ -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, + /// 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(()) } diff --git a/src/subcommands/package.rs b/src/subcommands/package.rs index e0f70aa..4f8a8d2 100644 --- a/src/subcommands/package.rs +++ b/src/subcommands/package.rs @@ -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::(&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)?;