fix tag feature to support custom tags

This commit is contained in:
Michael Angelo Calimlim 2023-10-17 23:02:41 +08:00
parent c2765a2267
commit c4a52ce838
8 changed files with 135 additions and 53 deletions

View file

@ -4,9 +4,10 @@ use crate::ftw_error::FtwError;
use crate::ftw_machine_type::FtwMachineType;
use crate::ftw_node_type::FtwNodeType;
use crate::ftw_success::FtwSuccess;
use crate::ftw_tag::FtwTag;
use crate::ftw_target::FtwTarget;
use crate::ftw_template::FtwTemplate;
use crate::traits::{Compiler, Processor, Runner, ToCliArg};
use crate::traits::{Compiler, Processor, Runner, ToCliArg, ToGitTag, ToGitUrl};
use crate::type_alias::{ClassName, FtwResult, ProjectName};
use crate::util;
@ -29,6 +30,7 @@ pub enum FtwCommand {
New {
project_name: ProjectName,
template: FtwTemplate,
tag: FtwTag,
},
Class {
class_name: ClassName,
@ -53,21 +55,22 @@ pub enum FtwCommand {
#[rustfmt::skip::macros(cmd, format)]
impl FtwCommand {
fn generate_project(project_name: &str, template: &FtwTemplate) -> Result<(), FtwError> {
let (git_url, tag) = match template {
FtwTemplate::Default { git_url, tag } | FtwTemplate::Custom { git_url, tag } => {
(git_url.to_string(), tag.clone())
}
};
fn generate_project(
project_name: &str,
template: &FtwTemplate,
tag: &FtwTag,
) -> Result<(), FtwError> {
let git_url = &template.to_git_url();
let git_tag = &tag.to_git_tag();
let template_path = TemplatePath {
git: Some(git_url),
git: Some(git_url.to_string()),
branch: None,
favorite: None,
subfolder: None,
path: None,
auto_path: None,
test: false,
tag,
tag: Some(git_tag.to_string()),
};
let generate_args = GenerateArgs {
template_path,
@ -178,7 +181,7 @@ impl FtwCommand {
let is_file = path.is_file();
if is_file {
let mut file_contents = String::new();
let mut file = File::open(&entry.path())?;
let mut file = File::open(entry.path())?;
file.read_to_string(&mut file_contents)?;
let is_native_class = FtwCommand::is_derving_native_class(&file_contents)?;
if is_native_class {
@ -328,7 +331,7 @@ impl FtwCommand {
let mut tmpl_globals = FtwCommand::get_tmpl_globals(class_name, node_type);
let k = KStringBase::from_ref("dir_path");
let v = Value::Scalar(ScalarCow::from(if directories.is_empty() {
"".to_string()
String::new()
} else {
let mut dir = directories.join("/");
dir.push('/');
@ -367,8 +370,8 @@ impl FtwCommand {
impl Processor for FtwCommand {
fn process(&self) -> FtwResult {
match self {
FtwCommand::New { project_name, template } => {
FtwCommand::generate_project(project_name, template)?;
FtwCommand::New { project_name, template, tag } => {
FtwCommand::generate_project(project_name, template, tag)?;
FtwCommand::append_to_gitignore(project_name)?;
FtwCommand::delete_items(project_name)?;
let project_name = project_name.to_string();
@ -443,6 +446,7 @@ mod ftw_command_tests {
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -462,6 +466,7 @@ mod ftw_command_tests {
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
assert!(project.exists(".gitignore"));
@ -491,6 +496,7 @@ mod ftw_command_tests {
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -534,6 +540,7 @@ mod ftw_command_tests {
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -579,6 +586,7 @@ mod ftw_command_tests {
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -634,6 +642,7 @@ mod ftw_command_tests {
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -669,6 +678,7 @@ mod ftw_command_tests {
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -697,6 +707,7 @@ mod ftw_command_tests {
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]
@ -734,6 +745,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]
@ -771,6 +783,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]
@ -808,6 +821,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]
@ -845,6 +859,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]
@ -882,6 +897,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -911,6 +927,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -939,6 +956,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let _ = env::set_current_dir(Path::new(&project.get_name()));
@ -980,6 +998,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]
@ -1030,6 +1049,7 @@ enable-cross-compilation=true
let cmd = FtwCommand::New {
project_name: project.get_name(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
let _ = cmd.process();
let contents = r#"[ftw]

View file

@ -48,8 +48,8 @@ impl ToMessage for FtwSuccess<'_> {
let description = match self {
FtwSuccess::New { project_name, template } => {
match template {
FtwTemplate::Default { git_url, tag } | FtwTemplate::Custom { git_url, tag } => {
format!("A new project has been created {} using the {} ({} {}) template", project_name.blue().bold().italic(), template.to_string().blue().bold().italic(), git_url.underline(), tag.clone().unwrap_or_default().underline())
FtwTemplate::Default { git_url } | FtwTemplate::Custom { git_url } => {
format!("A new project has been created {} using the {} ({}) template", project_name.blue().bold().italic(), template.to_string().blue().bold().italic(), git_url.underline())
}
}
},
@ -72,20 +72,19 @@ mod ftw_success_tests {
fn test_to_message() {
let new_game = "my-awesome-game".to_string();
let default_template = FtwTemplate::default();
if let FtwTemplate::Default { git_url, tag } = FtwTemplate::default() {
if let FtwTemplate::Default { git_url } = FtwTemplate::default() {
let ftw_success_new_default = FtwSuccess::New {
project_name: new_game.clone(),
template: &default_template,
};
assert_eq!(
format!(
"{} {} A new project has been created {} using the {} ({} {}) template",
"{} {} A new project has been created {} using the {} ({}) template",
FtwSuccess::THUMBS_UP,
FtwSuccess::get_styled_success(),
new_game.blue().bold().italic(),
default_template.to_string().blue().bold().italic(),
git_url.underline(),
tag.unwrap_or_default().underline(),
),
format!("{}", ftw_success_new_default.to_message())
);
@ -227,26 +226,20 @@ mod ftw_success_tests {
let new_game = "my-awesome-game".to_string();
let custom_template = FtwTemplate::Custom {
git_url: "/path/to/custom/template".to_string(),
tag: None,
};
if let FtwTemplate::Custom {
ref git_url,
ref tag,
} = custom_template
{
if let FtwTemplate::Custom { ref git_url } = custom_template {
let ftw_success_new_custom = FtwSuccess::New {
project_name: new_game.clone(),
template: &custom_template,
};
assert_eq!(
format!(
"{} {} A new project has been created {} using the {} ({} {}) template",
"{} {} A new project has been created {} using the {} ({}) template",
FtwSuccess::THUMBS_UP,
FtwSuccess::get_styled_success(),
new_game.blue().bold().italic(),
custom_template.to_string().blue().bold().italic(),
git_url.underline(),
tag.clone().unwrap_or_default().underline(),
),
format!("{}", ftw_success_new_custom.to_message())
);

52
src/ftw_tag.rs Normal file
View file

@ -0,0 +1,52 @@
use crate::traits::ToGitTag;
use crate::type_alias::GitTag;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::str::FromStr;
#[derive(Debug, Eq, PartialEq)]
pub enum FtwTag {
Latest {},
Tagged { tag: GitTag },
}
const DEFAULT_TEMPLATE_TAG: &str = "v1.0.0";
impl FromStr for FtwTag {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"latest" => Ok(FtwTag::default()),
tag => Ok(FtwTag::Tagged {
tag: tag.to_string(),
}),
}
}
}
impl ToGitTag for FtwTag {
fn to_git_tag(&self) -> GitTag {
match self {
FtwTag::Latest {} => DEFAULT_TEMPLATE_TAG,
FtwTag::Tagged { tag } => tag,
}
.to_string()
}
}
impl Display for FtwTag {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let message = match self {
FtwTag::Latest {} => "latest",
FtwTag::Tagged { tag } => tag,
};
write!(f, "{}", message)
}
}
impl Default for FtwTag {
fn default() -> Self {
FtwTag::Latest {}
}
}

View file

@ -1,22 +1,17 @@
use crate::type_alias::{GitTag, GitUrl};
use crate::traits::ToGitUrl;
use crate::type_alias::GitUrl;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::str::FromStr;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum FtwTemplate {
Default {
git_url: GitUrl,
tag: Option<GitTag>,
},
Custom {
git_url: GitUrl,
tag: Option<GitTag>,
},
Default { git_url: GitUrl },
Custom { git_url: GitUrl },
}
const DEFAULT_TEMPLATE_URL: &str = "https://github.com/macalimlim/godot-rust-template";
const DEFAULT_TEMPLATE_TAG: &str = "v1.0.0";
impl FromStr for FtwTemplate {
type Err = ();
@ -25,17 +20,25 @@ impl FromStr for FtwTemplate {
"default" => Ok(FtwTemplate::default()),
git_url => Ok(FtwTemplate::Custom {
git_url: git_url.to_string(),
tag: None,
}),
}
}
}
impl ToGitUrl for FtwTemplate {
fn to_git_url(&self) -> GitUrl {
match self {
FtwTemplate::Default { git_url } | FtwTemplate::Custom { git_url } => git_url,
}
.to_string()
}
}
impl Display for FtwTemplate {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let message = match self {
FtwTemplate::Default { git_url: _, tag: _ } => "default",
FtwTemplate::Custom { git_url: _, tag: _ } => "custom",
FtwTemplate::Default { git_url: _ } => "default",
FtwTemplate::Custom { git_url: _ } => "custom",
};
write!(f, "{}", message)
}
@ -45,7 +48,6 @@ impl Default for FtwTemplate {
fn default() -> Self {
FtwTemplate::Default {
git_url: DEFAULT_TEMPLATE_URL.to_string(),
tag: Some(DEFAULT_TEMPLATE_TAG.to_string()),
}
}
}
@ -64,7 +66,6 @@ mod ftw_template_tests {
assert_eq!(
FtwTemplate::Custom {
git_url: custom_template.clone(),
tag: None
},
custom_template.parse()?
);
@ -73,18 +74,15 @@ mod ftw_template_tests {
#[test]
fn test_to_git_url() {
if let FtwTemplate::Default { git_url, tag } = FtwTemplate::default() {
if let FtwTemplate::Default { git_url } = FtwTemplate::default() {
assert_eq!(git_url, DEFAULT_TEMPLATE_URL);
assert_eq!(tag.unwrap_or_default(), DEFAULT_TEMPLATE_TAG);
}
let custom_template = CUSTOM_TEMPLATE.to_string();
let tpl = FtwTemplate::Custom {
git_url: custom_template.clone(),
tag: None,
};
if let FtwTemplate::Custom { git_url, tag } = tpl {
if let FtwTemplate::Custom { git_url } = tpl {
assert_eq!(git_url, custom_template);
assert_eq!(tag, None);
}
}
@ -101,7 +99,6 @@ mod ftw_template_tests {
"{}",
FtwTemplate::Custom {
git_url: custom_template,
tag: None
}
)
);
@ -113,7 +110,6 @@ mod ftw_template_tests {
FtwTemplate::default(),
FtwTemplate::Default {
git_url: DEFAULT_TEMPLATE_URL.to_string(),
tag: Some(DEFAULT_TEMPLATE_TAG.to_string())
}
);
}
@ -123,7 +119,7 @@ mod ftw_template_tests {
fn test_from_str_custom(template_input in "\\PC*") {
prop_assume!(template_input != "default");
prop_assert!(template_input.parse::<FtwTemplate>().is_ok());
prop_assert_eq!(FtwTemplate::Custom{git_url: template_input.to_string(), tag: None}, template_input.parse::<FtwTemplate>().unwrap());
prop_assert_eq!(FtwTemplate::Custom{git_url: template_input.to_string()}, template_input.parse::<FtwTemplate>().unwrap());
}
}
}

View file

@ -6,6 +6,7 @@ pub mod ftw_error;
pub mod ftw_machine_type;
pub mod ftw_node_type;
pub mod ftw_success;
pub mod ftw_tag;
pub mod ftw_target;
pub mod ftw_template;
pub mod run_command;

View file

@ -6,6 +6,7 @@ mod ftw_error;
mod ftw_machine_type;
mod ftw_node_type;
mod ftw_success;
mod ftw_tag;
mod ftw_target;
mod ftw_template;
mod run_command;
@ -15,7 +16,9 @@ mod type_alias;
mod util;
use crate::ftw_command::FtwCommand;
use crate::ftw_tag::FtwTag;
use crate::traits::{Processor, ToMessage};
use clap::{
arg, command, crate_authors, crate_description, crate_name, crate_version, ArgMatches, Command,
};
@ -40,7 +43,8 @@ fn get_clap_command() -> Command {
Command::new("new")
.about("create a new godot-rust project directory")
.arg(arg!(<project_name> "set the name of your project"))
.arg(arg!([template] "set the template to be used in your project")),
.arg(arg!([template] "set the template to be used in your project"))
.arg(arg!([tag] "it can be any tag defined in the template or 'latest'")),
)
.subcommand(
Command::new("class")
@ -85,9 +89,15 @@ fn parse_matches(matches: &ArgMatches) -> FtwCommand {
.unwrap_or(&String::from("default"))
.parse()
.unwrap_or_default();
let tag = args
.get_one::<String>("tag")
.unwrap_or(&String::from("latest"))
.parse::<FtwTag>()
.unwrap_or_default();
FtwCommand::New {
project_name,
template,
tag,
}
}
Some(("class", args)) => {
@ -174,6 +184,7 @@ mod main_tests {
let cmd = FtwCommand::New {
project_name: project_name.to_string(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
assert_eq!(command, cmd);
}
@ -188,6 +199,7 @@ mod main_tests {
let cmd = FtwCommand::New {
project_name: project_name.to_string(),
template: FtwTemplate::default(),
tag: FtwTag::default(),
};
assert_eq!(command, cmd);
}
@ -204,8 +216,8 @@ mod main_tests {
project_name: project_name.to_string(),
template: FtwTemplate::Custom {
git_url: git_url.to_string(),
tag: None,
},
tag: FtwTag::default(),
};
assert_eq!(command, cmd);
}

View file

@ -1,6 +1,6 @@
use crate::ftw_error::FtwError;
use crate::type_alias::{
AppExt, CliArg, ExportArg, ExportName, FtwResult, LibExt, LibPrefix, Message,
AppExt, CliArg, ExportArg, ExportName, FtwResult, GitTag, GitUrl, LibExt, LibPrefix, Message,
};
pub trait Processor {
@ -32,6 +32,14 @@ pub trait Compiler {
fn export(&self) -> Result<(), FtwError>;
}
pub trait ToGitUrl {
fn to_git_url(&self) -> GitUrl;
}
pub trait ToGitTag {
fn to_git_tag(&self) -> GitTag;
}
pub trait ToCliArg {
fn to_cli_arg(&self) -> CliArg;
}

View file

@ -63,7 +63,7 @@ struct Package {
pub fn get_crate_name_from_path(path: &str) -> Result<String, FtwError> {
let cargo_file = Path::new(path).join("Cargo.toml");
let mut file_contents = String::new();
let mut file = File::open(&cargo_file.as_path())?;
let mut file = File::open(cargo_file.as_path())?;
file.read_to_string(&mut file_contents)?;
let cargo_toml: CargoToml = toml::from_str(file_contents.as_str())?;
let crate_name = cargo_toml