Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "star-setup"
version = "0.3.1"
version = "0.3.2"
edition = "2021"
repository = "https://github.com/star-setup/core"
description = "Lightweight CLI to clone, configure, and wire single or multi-repo ecosystems"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ cargo install --git https://github.com/star-setup/core
|------|-------------|
| `--build-type <TYPE>` | Build type: `Debug` (default) or `Release` |
| `--build-dir <DIR>` | Build output directory (default: `build`) |
| `--build-system <SYSTEM>` | Skip auto-detection and use `cmake` or `meson` |
| `--no-build` | Configure only, skip build step |
| `--clean` | Remove build directory before configuring |
| `--cmake-arg <ARG>` | Pass additional argument to CMake |
Expand Down
15 changes: 15 additions & 0 deletions src/cli/build/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ impl BuildType {
}
}

impl std::str::FromStr for BuildSystem {
type Err = String;

/// Parses a build system string.
/// # Errors
/// Returns an error if the string does not match `cmake` or `meson`.
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"cmake" => Ok(Self::Cmake),
"meson" => Ok(Self::Meson),
_ => Err(format!("Unknown build system '{s}'. Valid: cmake, meson")),
}
}
}

impl std::str::FromStr for BuildType {
type Err = String;

Expand Down
6 changes: 6 additions & 0 deletions src/cli/flags.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::cli::BuildSystem;
use clap::Args as ClapArgs;

#[allow(clippy::struct_excessive_bools)]
Expand Down Expand Up @@ -29,6 +30,10 @@ pub struct BuildFlags {
#[arg(short = 'd', long)]
pub build_dir: Option<String>,

/// Build system to use, skipping auto-detection
#[arg(long, value_name = "BUILD_SYSTEM")]
pub build_system: Option<BuildSystem>,

/// Skip building, only configure
#[arg(short = 'n', long, conflicts_with = "build")]
pub no_build: bool,
Expand Down Expand Up @@ -115,6 +120,7 @@ pub struct DiagnosticFlags {
/// Show timing information for each phase
#[arg(long)]
pub timing: bool,

/// If set, print commands instead of executing them without making any changes.
#[arg(long)]
pub dry_run: bool,
Expand Down
1 change: 1 addition & 0 deletions src/cli/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub fn resolve_with_config(mut args: Args, config: &SetupConfig) -> Result<Resol
.build_dir
.or_else(|| default.map(|e| e.build_dir.clone()))
.unwrap_or_else(|| "build".to_string()),
build_system: args.build.build_system,
no_build,
clean,
cmake_flags: args.build.cmake_flags,
Expand Down
3 changes: 2 additions & 1 deletion src/cli/resolved.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::cli::{BuildType, ConfigFlags, ProfileFlags};
use crate::cli::{BuildSystem, BuildType, ConfigFlags, ProfileFlags};

/// Resolved connection flags after applying config and CLI overrides.
pub struct ResolvedConnectionFlags {
Expand All @@ -16,6 +16,7 @@ pub struct ResolvedDiagnosticFlags {
pub struct ResolvedBuildFlags {
pub build_type: BuildType,
pub build_dir: String,
pub build_system: Option<BuildSystem>,
pub no_build: bool,
pub clean: bool,
pub cmake_flags: Vec<String>,
Expand Down
26 changes: 13 additions & 13 deletions src/commands/mono/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,22 @@ pub fn mono_repo_mode(

let build_path = mono_repo_path.join(&args.build.build_dir);

let canonical_map = if ctx.io.dry_run {
prepare_build_dir(build_path.as_path(), args.build.clean, ctx)?;
None
let build_system = if let Some(bs) = args.build.build_system {
Some(bs)
} else if !ctx.io.dry_run {
Some(detect_mono_build_system(&repo_dirs, ctx)?)
} else {
let build_system = detect_mono_build_system(&repo_dirs, ctx)?;
let map = generate_mono_config(
build_system,
&mono_repo_path,
&repos_path,
&repo_dirs,
&repos,
ctx,
)?;
None
};

let canonical_map = if let Some(bs) = build_system {
let map = generate_mono_config(bs, &mono_repo_path, &repos_path, &repo_dirs, &repos, ctx)?;
prepare_build_dir(build_path.as_path(), args.build.clean, ctx)?;
configure_and_build(args, &mono_repo_path, &build_path, build_system, true, ctx)?;
configure_and_build(args, &mono_repo_path, &build_path, bs, true, ctx)?;
map
} else {
prepare_build_dir(build_path.as_path(), args.build.clean, ctx)?;
None
};

let paths = if ctx.io.dry_run {
Expand Down
11 changes: 9 additions & 2 deletions src/commands/single.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,15 @@ pub fn single_repo_mode(
let build_path = repo_path.join(&args.build.build_dir);
prepare_build_dir(&build_path, args.build.clean, ctx)?;

if !ctx.io.dry_run {
let build_system = detect_build_system(&repo_path, ctx)?;
let build_system = if let Some(bs) = args.build.build_system {
Some(bs)
} else if !ctx.io.dry_run {
Some(detect_build_system(&repo_path, ctx)?)
} else {
None
};

if let Some(build_system) = build_system {
configure_and_build(args, &repo_path, &build_path, build_system, false, ctx)?;
}

Expand Down
19 changes: 16 additions & 3 deletions src/config/crud.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,20 @@ pub fn add_config(
}

if io.dry_run {
writeln!(io.output, "Would save configuration '{name}' to config file").ok();
writeln!(
io.output,
"Would save configuration '{name}' to config file"
)
.ok();
} else {
insert_config(config, name, entry);
let path = save_config(config)?;
writeln!(io.output, "Configuration '{name}' added successfully to {}", path.display()).ok();
writeln!(
io.output,
"Configuration '{name}' added successfully to {}",
path.display()
)
.ok();
let e: &ConfigEntry = &config.configs[name];
writeln!(io.output, "Configuration details:").ok();
write!(io.output, "{}", format_entry(e)).ok();
Expand Down Expand Up @@ -132,7 +141,11 @@ pub fn remove_config(
}

if io.dry_run {
writeln!(io.output, "Would remove configuration '{name}' from config file").ok();
writeln!(
io.output,
"Would remove configuration '{name}' from config file"
)
.ok();
} else {
remove_config_entry(config, name);
let path = save_config(config)?;
Expand Down
2 changes: 2 additions & 0 deletions tests/cli.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#[path = "cli/build.rs"]
mod build;
#[path = "common/mod.rs"]
mod common;
#[path = "cli/resolve.rs"]
mod resolve;
11 changes: 11 additions & 0 deletions tests/cli/build/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,14 @@ fn test_from_str_error() {
use std::str::FromStr;
assert!(BuildType::from_str("unknown").is_err());
}

#[test]
fn test_build_system_from_str() {
use star_setup::cli::BuildSystem;
use std::str::FromStr;
assert_eq!(BuildSystem::from_str("cmake").unwrap(), BuildSystem::Cmake);
assert_eq!(BuildSystem::from_str("CMAKE").unwrap(), BuildSystem::Cmake);
assert_eq!(BuildSystem::from_str("meson").unwrap(), BuildSystem::Meson);
assert_eq!(BuildSystem::from_str("MESON").unwrap(), BuildSystem::Meson);
assert!(BuildSystem::from_str("ninja").is_err());
}
51 changes: 2 additions & 49 deletions tests/cli/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::common::default_args;
use star_setup::{
cli::{
resolve_bool, resolve_with_config, Args, BuildFlags, BuildType, ConfigFlags, ConnectionFlags,
DiagnosticFlags, MonoRepoFlags, ProfileFlags,
},
cli::{resolve_bool, resolve_with_config, BuildType},
config::{ConfigEntry, SetupConfig},
};

Expand Down Expand Up @@ -71,51 +69,6 @@ fn test_resolve_bool() {
}
}

fn default_args() -> Args {
Args {
repo: None,
yes: false,
diagnostic: DiagnosticFlags {
timing: false,
dry_run: false,
},
connection: ConnectionFlags {
ssh: false,
https: false,
verbose: false,
no_verbose: false,
},
build: BuildFlags {
build_type: None,
build_dir: None,
no_build: false,
build: false,
clean: false,
no_clean: false,
cmake_flags: vec![],
meson_flags: vec![],
},
mono: MonoRepoFlags {
mono_repo: false,
mono_dir: None,
repos: None,
profile: None,
},
config: ConfigFlags {
init_config: false,
config_name: None,
config_add: None,
config_remove: None,
list_configs: false,
},
profile: ProfileFlags {
profile_add: None,
profile_remove: None,
list_profiles: false,
},
}
}

// resolve_with_config tests
#[test]
fn test_resolve_with_config_defaults_when_no_config() {
Expand Down
68 changes: 9 additions & 59 deletions tests/commands/build.rs
Original file line number Diff line number Diff line change
@@ -1,65 +1,15 @@
use super::common::{empty_input, make_io, sink, MockRunner};
use super::common::{default_resolved_with_no_build, empty_input, make_io, sink, MockRunner};
use star_setup::{
cli::{
resolve_with_config, Args, BuildFlags, BuildSystem, ConfigFlags, ConnectionFlags,
DiagnosticFlags, MonoRepoFlags, ProfileFlags,
},
cli::BuildSystem,
commands::{build_project, cmake_build, meson_build},
config::SetupConfig,
ctx::RunCtx,
};
use tempfile::TempDir;

fn default_resolved(no_build: bool) -> star_setup::cli::ResolvedArgs {
let args = Args {
repo: Some("user/repo".to_string()),
yes: false,
diagnostic: DiagnosticFlags {
timing: false,
dry_run: false,
},
connection: ConnectionFlags {
ssh: false,
https: false,
verbose: false,
no_verbose: false,
},
build: BuildFlags {
build_type: None,
build_dir: None,
no_build,
build: false,
clean: false,
no_clean: false,
cmake_flags: vec![],
meson_flags: vec![],
},
mono: MonoRepoFlags {
mono_repo: false,
mono_dir: None,
repos: None,
profile: None,
},
config: ConfigFlags {
init_config: false,
config_name: None,
config_add: None,
config_remove: None,
list_configs: false,
},
profile: ProfileFlags {
profile_add: None,
profile_remove: None,
list_profiles: false,
},
};
resolve_with_config(args, &SetupConfig::new()).unwrap()
}

#[test]
fn test_cmake_build_configure_only() {
let tmp = TempDir::new().unwrap();
let args = default_resolved(true);
let args = default_resolved_with_no_build(true);
let mut input = empty_input();
let mut output = sink();
let mut runner = MockRunner::new();
Expand All @@ -77,7 +27,7 @@ fn test_cmake_build_configure_only() {
#[test]
fn test_cmake_build_with_build_step() {
let tmp = TempDir::new().unwrap();
let args = default_resolved(false);
let args = default_resolved_with_no_build(false);
let mut input = empty_input();
let mut output = sink();
let mut runner = MockRunner::new();
Expand All @@ -95,7 +45,7 @@ fn test_cmake_build_with_build_step() {
#[test]
fn test_cmake_build_mono_flag() {
let tmp = TempDir::new().unwrap();
let args = default_resolved(true);
let args = default_resolved_with_no_build(true);
let mut input = empty_input();
let mut output = sink();
let mut runner = MockRunner::new();
Expand All @@ -112,7 +62,7 @@ fn test_cmake_build_mono_flag() {
#[test]
fn test_meson_build_configure_only() {
let tmp = TempDir::new().unwrap();
let args = default_resolved(true);
let args = default_resolved_with_no_build(true);
let mut input = empty_input();
let mut output = sink();
let mut runner = MockRunner::new();
Expand All @@ -131,7 +81,7 @@ fn test_meson_build_configure_only() {
#[test]
fn test_meson_build_with_build_step() {
let tmp = TempDir::new().unwrap();
let args = default_resolved(false);
let args = default_resolved_with_no_build(false);
let mut input = empty_input();
let mut output = sink();
let mut runner = MockRunner::new();
Expand All @@ -149,7 +99,7 @@ fn test_meson_build_with_build_step() {
#[test]
fn test_build_project_dispatches_cmake() {
let tmp = TempDir::new().unwrap();
let args = default_resolved(true);
let args = default_resolved_with_no_build(true);
let mut input = empty_input();
let mut output = sink();
let mut runner = MockRunner::new();
Expand All @@ -174,7 +124,7 @@ fn test_build_project_dispatches_cmake() {
#[test]
fn test_build_project_dispatches_meson() {
let tmp = TempDir::new().unwrap();
let args = default_resolved(true);
let args = default_resolved_with_no_build(true);
let mut input = empty_input();
let mut output = sink();
let mut runner = MockRunner::new();
Expand Down
Loading
Loading