Skip to content

Commit

Permalink
Merge pull request #1161 from spkenv/workspaces2
Browse files Browse the repository at this point in the history
Workspaces Part II
  • Loading branch information
rydrman authored Feb 11, 2025
2 parents 208f06e + 4710737 commit 95eef47
Show file tree
Hide file tree
Showing 16 changed files with 612 additions and 143 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions crates/spk-cli/cmd-make-recipe/src/cmd_make_recipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ impl Run for MakeRecipe {
let options = self.options.get_options()?;
let workspace = self.workspace.load_or_default()?;

let template = match self.package.as_ref() {
let configured = match self.package.as_ref() {
None => workspace.default_package_template(),
Some(p) => workspace.find_package_template(p),
}
.must_be_found();

if let Some(name) = template.name() {
if let Some(name) = configured.template.name() {
tracing::info!("rendering template for {name}");
} else {
tracing::info!("rendering template without a name");
Expand All @@ -62,15 +62,15 @@ impl Run for MakeRecipe {
let data = spk_schema::TemplateData::new(&options);
tracing::debug!("full template data: {data:#?}");
let rendered = spk_schema_tera::render_template(
template.file_path().to_string_lossy(),
template.source(),
configured.template.file_path().to_string_lossy(),
configured.template.source(),
&data,
)
.into_diagnostic()
.wrap_err("Failed to render template")?;
print!("{rendered}");

match template.render(&options) {
match configured.template.render(&options) {
Err(err) => {
tracing::error!("This template did not render into a valid spec {err}");
Ok(1)
Expand Down
26 changes: 15 additions & 11 deletions crates/spk-cli/common/src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,12 @@ impl Requests {
let path = std::path::Path::new(package);
if path.is_file() {
let workspace = self.workspace.load_or_default()?;
let template = workspace.find_package_template(&package).must_be_found();
let rendered_data = template.render(options)?;
let configured = workspace.find_package_template(package).must_be_found();
let rendered_data = configured.template.render(options)?;
let recipe = rendered_data.into_recipe().wrap_err_with(|| {
format!(
"{filename} was expected to contain a recipe",
filename = template.file_path().to_string_lossy()
filename = configured.template.file_path().to_string_lossy()
)
})?;
idents.push(recipe.ident().to_any_ident(None));
Expand Down Expand Up @@ -750,6 +750,10 @@ impl std::str::FromStr for PackageSpecifier {
#[derive(Args, Default, Clone)]
pub struct Packages {
/// The package names or yaml spec files to operate on
///
/// Package requests may also come with a version when multiple
/// versions might be found in the local workspace or configured
/// repositories.
#[clap(name = "PKG|SPEC_FILE")]
pub packages: Vec<PackageSpecifier>,

Expand Down Expand Up @@ -833,20 +837,20 @@ where
None => workspace.default_package_template(),
Some(package_name) => workspace.find_package_template(package_name),
};
let template = match from_workspace {
let configured = match from_workspace {
FindPackageTemplateResult::Found(template) => template,
res @ FindPackageTemplateResult::MultipleTemplateFiles(_) => {
// must_be_found() will exit the program when called on MultipleTemplateFiles
res.must_be_found();
unreachable!()
}
FindPackageTemplateResult::NoTemplateFiles | FindPackageTemplateResult::NotFound(_) => {
FindPackageTemplateResult::NoTemplateFiles | FindPackageTemplateResult::NotFound(..) => {
// If couldn't find a template file, maybe there's an
// existing package/version that's been published
match package_name.map(AsRef::as_ref) {
Some(name) if std::path::Path::new(name).is_file() => {
tracing::debug!(?name, "Loading anonymous template file into workspace...");
workspace.load_template_file(name)?.clone()
workspace.load_template_file(name)?
}
Some(name) => {
tracing::debug!("Unable to find package file: {}", name);
Expand Down Expand Up @@ -897,17 +901,17 @@ where
}
}
};
let found = template.render(options).wrap_err_with(|| {
let found = configured.template.render(options).wrap_err_with(|| {
format!(
"{filename} was expected to contain a valid spk yaml data file",
filename = template.file_path().to_string_lossy()
filename = configured.template.file_path().to_string_lossy()
)
})?;
tracing::debug!(
"Rendered template from the data in {:?}",
template.file_path()
"Rendered configured.template from the data in {:?}",
configured.template.file_path()
);
Ok((found, template.file_path().to_owned()))
Ok((found, configured.template.file_path().to_owned()))
}

#[derive(Args, Clone)]
Expand Down
6 changes: 3 additions & 3 deletions crates/spk-cli/group4/src/cmd_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,16 @@ impl View {
workspace: &spk_workspace::Workspace,
show_variants_with_tests: bool,
) -> Result<i32> {
let template = match self.package.as_ref() {
let configured = match self.package.as_ref() {
None => workspace.default_package_template(),
Some(name) => workspace.find_package_template(name),
}
.must_be_found();
let rendered_data = template.render(options)?;
let rendered_data = configured.template.render(options)?;
let recipe = rendered_data.into_recipe().wrap_err_with(|| {
format!(
"{filename} was expected to contain a recipe",
filename = template.file_path().to_string_lossy()
filename = configured.template.file_path().to_string_lossy()
)
})?;

Expand Down
10 changes: 8 additions & 2 deletions crates/spk-schema/crates/foundation/src/version_range/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,14 @@ pub struct LowestSpecifiedRange {
impl LowestSpecifiedRange {
pub const REQUIRED_NUMBER_OF_DIGITS: usize = 2;

pub fn new(specified: usize, base: Version) -> Self {
Self { specified, base }
pub fn new(mut base: Version) -> Self {
while base.parts.len() < Self::REQUIRED_NUMBER_OF_DIGITS {
base.parts.push(0);
}
Self {
specified: base.parts.len(),
base,
}
}
}

Expand Down
26 changes: 22 additions & 4 deletions crates/spk-schema/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// https://github.com/spkenv/spk

use std::borrow::Cow;
use std::collections::HashSet;
use std::io::Read;
use std::path::Path;
use std::str::FromStr;
Expand Down Expand Up @@ -136,23 +137,39 @@ macro_rules! spec {

/// A generic, structured data object that can be turned into a recipe
/// when provided with the necessary option values
#[derive(Debug)]
pub struct SpecTemplate {
name: Option<PkgNameBuf>,
versions: HashSet<Version>,
file_path: std::path::PathBuf,
template: String,
template: Arc<str>,
}

impl SpecTemplate {
/// The complete source string for this template
pub fn source(&self) -> &str {
&self.template
}
}

impl SpecTemplate {
/// The name of the item that this template will create.
pub fn name(&self) -> Option<&PkgNameBuf> {
self.name.as_ref()
}

/// The versions that are available to create with this template.
///
/// An empty set does not signify no versions, but rather that
/// nothing has been specified or discerned.
pub fn versions(&self) -> &HashSet<Version> {
&self.versions
}

/// Clear and reset the versions that are available to create
/// with this template.
pub fn set_versions(&mut self, versions: impl IntoIterator<Item = Version>) {
self.versions.clear();
self.versions.extend(versions);
}
}

impl Template for SpecTemplate {
Expand Down Expand Up @@ -251,7 +268,8 @@ impl TemplateExt for SpecTemplate {
Ok(Self {
file_path,
name,
template,
versions: Default::default(),
template: template.into(),
})
}
}
Expand Down
6 changes: 4 additions & 2 deletions crates/spk-schema/src/spec_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,8 @@ sources:
let tpl = SpecTemplate {
name: Some(PkgName::new("my-package").unwrap().to_owned()),
file_path: "my-package.spk.yaml".into(),
template: SPEC.to_string(),
versions: Default::default(),
template: SPEC.into(),
};
let options = option_map! {"version" => "1.0.0"};
let err = tpl
Expand All @@ -347,7 +348,8 @@ fn test_template_namespace_options() {
let tpl = SpecTemplate {
name: Some(PkgName::new("my-package").unwrap().to_owned()),
file_path: "my-package.spk.yaml".into(),
template: SPEC.to_string(),
versions: Default::default(),
template: SPEC.into(),
};
let options = option_map! {"namespace.version" => "1.0.0"};
let rendered_data = tpl
Expand Down
45 changes: 21 additions & 24 deletions crates/spk-schema/src/version_range_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,30 +263,27 @@ fn arb_lowest_specified_range_from_version(
0..=(*version.parts.get(parts_to_generate - 1).unwrap()),
)
.prop_map(|(version, parts_to_generate, last_element_value)| {
VersionRange::LowestSpecified(LowestSpecifiedRange::new(
parts_to_generate,
Version {
parts: version
.parts
.iter()
.take(parts_to_generate)
.enumerate()
.map(|(index, num)| {
if index == parts_to_generate - 1 {
last_element_value
} else {
*num
}
})
.collect::<Vec<_>>()
.into(),
// Retain pre and post from original version because
// if the original has pre it might be smaller than
// the smallest value we generated without it.
pre: version.pre,
post: version.post,
},
))
VersionRange::LowestSpecified(LowestSpecifiedRange::new(Version {
parts: version
.parts
.iter()
.take(parts_to_generate)
.enumerate()
.map(|(index, num)| {
if index == parts_to_generate - 1 {
last_element_value
} else {
*num
}
})
.collect::<Vec<_>>()
.into(),
// Retain pre and post from original version because
// if the original has pre it might be smaller than
// the smallest value we generated without it.
pre: version.pre,
post: version.post,
}))
})
},
)
Expand Down
1 change: 1 addition & 0 deletions crates/spk-workspace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ tracing = { workspace = true }
rstest = { workspace = true }
serde_json = { workspace = true }
tempfile = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
Loading

0 comments on commit 95eef47

Please # to comment.