From 9c4b18b911c7533e3d66a97856fa468fcc8c22dc Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Fri, 9 Aug 2024 12:50:14 +0200 Subject: [PATCH 1/3] Expose parts of the CLI implementation --- src/cli.rs | 40 +++++++++++++++++++++++++--------------- src/lib.rs | 1 + 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 33018e5..b5915a9 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -7,32 +7,53 @@ use std::env; #[derive(Args, Debug)] #[group(required = true, multiple = false)] -struct NameOrLanguage { +pub struct NameOrLanguage { + /// Name of the example to use #[arg(short, long, group = "ex")] example: Option, + /// Language to use for it's default example #[arg(short, long, alias = "lang", group = "ex")] language: Option, } +impl NameOrLanguage { + /// Gets the selected example's name + pub fn example_name(&self) -> ExampleName { + self.example + .clone() + .unwrap_or(ExampleName::from_string(format!( + "{}-default", + self.language.clone().unwrap_or(GuestLanguage::Rust).id() + ))) + } +} + #[derive(Subcommand, Debug)] #[command()] -enum Command { +pub enum Command { + /// Create a new Golem component from built-in examples #[command()] New { #[command(flatten)] name_or_language: NameOrLanguage, + /// The package name of the generated component (in namespace:name format) #[arg(short, long)] package_name: Option, + /// The new component's name component_name: ComponentName, }, + + /// Lists the built-in examples available for creating new components #[command()] ListExamples { + /// The minimum language tier to include in the list #[arg(short, long)] min_tier: Option, + /// Filter examples by a given guest language #[arg(short, long, alias = "lang")] language: Option, }, @@ -40,7 +61,7 @@ enum Command { #[derive(Parser, Debug)] #[command(author, version, about, long_about = None, rename_all = "kebab-case")] -struct GolemCommand { +pub struct GolemCommand { #[command(subcommand)] command: Command, } @@ -53,18 +74,7 @@ pub fn main() { component_name, package_name, } => { - let example_name = - name_or_language - .example - .clone() - .unwrap_or(ExampleName::from_string(format!( - "{}-default", - name_or_language - .language - .clone() - .unwrap_or(GuestLanguage::Rust) - .id() - ))); + let example_name = name_or_language.example_name(); let examples = GolemExamples::list_all_examples(); let example = examples.iter().find(|example| example.name == example_name); match example { diff --git a/src/lib.rs b/src/lib.rs index a92048b..fc531c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ use std::io::Write; use std::path::{Path, PathBuf}; use std::{fs, io}; +pub mod cli; pub mod model; pub trait Examples { From 486cfa1ed2508ed2e4302ba6f1083333c3c537bd Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Fri, 9 Aug 2024 12:53:16 +0200 Subject: [PATCH 2/3] Fix deps --- .github/workflows/ci.yaml | 2 +- Cargo.toml | 3 ++- src/lib.rs | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a195f70..a622c7d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -41,7 +41,7 @@ jobs: - name: Tests run: cargo test --all-features - name: List bundled examples - run: cargo run --features=build-binary list-examples + run: cargo run list-examples publish: needs: [ build ] if: "startsWith(github.ref, 'refs/tags/v')" diff --git a/Cargo.toml b/Cargo.toml index d8ac28c..666386e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,8 @@ copy_dir = "0.1.3" dir-diff = "0.3.3" [features] -build-binary = ["clap"] +default = ["cli"] +cli = ["dep:clap"] [lib] path = "src/lib.rs" diff --git a/src/lib.rs b/src/lib.rs index fc531c4..53097f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ use std::io::Write; use std::path::{Path, PathBuf}; use std::{fs, io}; +#[cfg(feature = "cli")] pub mod cli; pub mod model; From 3d6e330b4250142983e0e21d506810518e886f40 Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Fri, 9 Aug 2024 12:58:49 +0200 Subject: [PATCH 3/3] Fix --- Cargo.toml | 4 ++-- src/cli.rs | 62 +++++------------------------------------------------ src/main.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 59 deletions(-) create mode 100644 src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 666386e..c44e302 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,5 +35,5 @@ path = "src/lib.rs" [[bin]] name = "golem-examples-cli" -path = "src/cli.rs" -required-features = ["build-binary"] +path = "src/main.rs" +required-features = ["cli"] diff --git a/src/cli.rs b/src/cli.rs index b5915a9..e7edddf 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,20 +1,17 @@ use clap::*; -use golem_examples::model::{ - ComponentName, ExampleName, ExampleParameters, GuestLanguage, GuestLanguageTier, PackageName, -}; -use golem_examples::*; -use std::env; + +use crate::model::{ComponentName, ExampleName, GuestLanguage, GuestLanguageTier, PackageName}; #[derive(Args, Debug)] #[group(required = true, multiple = false)] pub struct NameOrLanguage { /// Name of the example to use #[arg(short, long, group = "ex")] - example: Option, + pub example: Option, /// Language to use for it's default example #[arg(short, long, alias = "lang", group = "ex")] - language: Option, + pub language: Option, } impl NameOrLanguage { @@ -63,54 +60,5 @@ pub enum Command { #[command(author, version, about, long_about = None, rename_all = "kebab-case")] pub struct GolemCommand { #[command(subcommand)] - command: Command, -} - -pub fn main() { - let command: GolemCommand = GolemCommand::parse(); - match &command.command { - Command::New { - name_or_language, - component_name, - package_name, - } => { - let example_name = name_or_language.example_name(); - let examples = GolemExamples::list_all_examples(); - let example = examples.iter().find(|example| example.name == example_name); - match example { - Some(example) => { - let cwd = env::current_dir().expect("Failed to get current working directory"); - match GolemExamples::instantiate( - example, - ExampleParameters { - component_name: component_name.clone(), - package_name: package_name - .clone() - .unwrap_or(PackageName::from_string("golem:component").unwrap()), - target_path: cwd, - }, - ) { - Ok(instructions) => println!("{instructions}"), - Err(err) => eprintln!("Failed to instantiate example: {err}"), - } - } - None => { - eprintln!("Unknown example {example_name}. Use the list-examples command to see the available commands."); - } - } - } - Command::ListExamples { min_tier, language } => { - GolemExamples::list_all_examples() - .iter() - .filter(|example| match language { - Some(language) => example.language == *language, - None => true, - }) - .filter(|example| match min_tier { - Some(min_tier) => example.language.tier() <= *min_tier, - None => true, - }) - .for_each(|example| println!("{:?}", example)); - } - } + pub command: Command, } diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2a4c7d1 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,54 @@ +use clap::Parser; +use golem_examples::cli::*; +use golem_examples::model::*; +use golem_examples::{Examples, GolemExamples}; +use std::env; + +pub fn main() { + let command: GolemCommand = GolemCommand::parse(); + match &command.command { + Command::New { + name_or_language, + component_name, + package_name, + } => { + let example_name = name_or_language.example_name(); + let examples = GolemExamples::list_all_examples(); + let example = examples.iter().find(|example| example.name == example_name); + match example { + Some(example) => { + let cwd = env::current_dir().expect("Failed to get current working directory"); + match GolemExamples::instantiate( + example, + ExampleParameters { + component_name: component_name.clone(), + package_name: package_name + .clone() + .unwrap_or(PackageName::from_string("golem:component").unwrap()), + target_path: cwd, + }, + ) { + Ok(instructions) => println!("{instructions}"), + Err(err) => eprintln!("Failed to instantiate example: {err}"), + } + } + None => { + eprintln!("Unknown example {example_name}. Use the list-examples command to see the available commands."); + } + } + } + Command::ListExamples { min_tier, language } => { + GolemExamples::list_all_examples() + .iter() + .filter(|example| match language { + Some(language) => example.language == *language, + None => true, + }) + .filter(|example| match min_tier { + Some(min_tier) => example.language.tier() <= *min_tier, + None => true, + }) + .for_each(|example| println!("{:?}", example)); + } + } +}