Skip to content
This repository has been archived by the owner on Feb 26, 2025. It is now read-only.

Commit

Permalink
composable fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
noise64 committed Jan 16, 2025
1 parent 3032c65 commit d52a81f
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 72 deletions.
3 changes: 2 additions & 1 deletion examples/c/c-app-common/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
"requiresWASI": true,
"witDepsPaths": [
"common-wit-deps"
]
],
"transform": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
# yaml-language-server: $schema=https://schema.golem.cloud/app/golem/1.1.0/golem.schema.json

components:
app:component-e:
pack:name:
template: cpp
2 changes: 1 addition & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl NameOrLanguage {
.clone()
.unwrap_or(ExampleName::from_string(format!(
"{}-default",
self.language.clone().unwrap_or(GuestLanguage::Rust).id()
self.language.unwrap_or(GuestLanguage::Rust).id()
)))
}
}
Expand Down
143 changes: 83 additions & 60 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::model::{
};
use include_dir::{include_dir, Dir, DirEntry};
use itertools::Itertools;
use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet};
use std::path::{Path, PathBuf};
use std::{fs, io};
Expand Down Expand Up @@ -126,11 +127,13 @@ pub fn instantiate_example(
)?;
if let Some(adapter_path) = &example.adapter_source {
let adapter_dir = {
match &example.adapter_target {
Some(target) => target.clone(),
None => parameters.target_path.join("adapters"),
}
.join(example.language.tier().name())
parameters
.target_path
.join(match &example.adapter_target {
Some(target) => target.clone(),
None => parameters.target_path.join("adapters"),
})
.join(example.language.tier().name())
};

fs::create_dir_all(&adapter_dir)?;
Expand Down Expand Up @@ -245,14 +248,25 @@ fn instantiate_file(
resolve_mode: TargetExistsResolveMode,
) -> io::Result<()> {
match get_resolved_contents(catalog, source, target, resolve_mode)? {
Some(contents) => fs::write(
target,
Some(contents) => {
if transform_contents {
transform(&contents, parameters)
fs::write(
target,
transform(
std::str::from_utf8(contents.as_ref()).map_err(|err| {
io::Error::other(format!(
"Failed to decode as utf8, source: {}, err: {}",
source.display(),
err
))
})?,
parameters,
),
)
} else {
contents
},
),
fs::write(target, contents)
}
}
None => Ok(()),
}
}
Expand Down Expand Up @@ -346,15 +360,25 @@ fn check_target(

match file_name {
".gitignore" => {
let current_content = fs::read_to_string(target)?;
let target = target.to_path_buf();
let current_content = fs::read_to_string(&target)?;
Ok(Some(TargetExistsResolveDecision::Merge(Box::new(
move |new_content: &str| -> String {
current_content
move |new_content: &[u8]| -> io::Result<Vec<u8>> {
Ok(current_content
.lines()
.chain(new_content.lines())
.chain(
std::str::from_utf8(new_content).map_err(|err| {
io::Error::other(format!(
"Failed to decode new content for merge as utf8, target: {}, err: {}",
target.display(),
err
))
})?.lines(),
)
.collect::<BTreeSet<&str>>()
.iter()
.join("\n")
.into_bytes())
},
))))
}
Expand Down Expand Up @@ -383,34 +407,24 @@ fn check_target(
}
}

fn get_contents(catalog: &Dir<'_>, source: &Path) -> io::Result<String> {
String::from_utf8(
catalog
.get_file(source)
.ok_or_else(|| io::Error::other(format!("Could not find entry {}", source.display())))?
.contents()
.to_vec(),
)
.map_err(|err| {
io::Error::other(format!(
"Could not parse utf8 contents for {}: {:?}",
source.display(),
err
))
})
fn get_contents<'a>(catalog: &Dir<'a>, source: &'a Path) -> io::Result<&'a [u8]> {
Ok(catalog
.get_file(source)
.ok_or_else(|| io::Error::other(format!("Could not find entry {}", source.display())))?
.contents())
}

fn get_resolved_contents(
catalog: &Dir<'_>,
source: &Path,
target: &Path,
fn get_resolved_contents<'a>(
catalog: &Dir<'a>,
source: &'a Path,
target: &'a Path,
resolve_mode: TargetExistsResolveMode,
) -> io::Result<Option<String>> {
) -> io::Result<Option<Cow<'a, [u8]>>> {
match check_target(target, resolve_mode)? {
None => Ok(Some(get_contents(catalog, source)?)),
None => Ok(Some(Cow::Borrowed(get_contents(catalog, source)?))),
Some(TargetExistsResolveDecision::Skip) => Ok(None),
Some(TargetExistsResolveDecision::Merge(merge)) => {
Ok(Some(merge(&get_contents(catalog, source)?)))
Ok(Some(Cow::Owned(merge(get_contents(catalog, source)?)?)))
}
}
}
Expand All @@ -428,16 +442,39 @@ fn parse_example(
.contents();
let metadata = serde_json::from_slice::<ExampleMetadata>(raw_metadata)
.expect("Failed to parse metadata JSON");
let instructions_path = match metadata.instructions {
Some(instructions_file_name) => lang_path.join(instructions_file_name),
None => lang_path.join(default_instructions_file_name),

let kind = match (metadata.app_common_group, metadata.app_component_group) {
(None, None) => ExampleKind::Standalone,
(Some(group), None) => ExampleKind::ComposableAppCommon {
group: ComposableAppGroupName::from_string(group),
},
(None, Some(group)) => ExampleKind::ComposableAppComponent {
group: ComposableAppGroupName::from_string(group),
},
(Some(_), Some(_)) => panic!(
"Only one of appCommonGroup and appComponentGroup can be specified, example root: {}",
example_root.display()
),
};
let raw_instructions = EXAMPLES
.get_file(instructions_path)
.expect("Failed to read instructions")
.contents();
let instructions =
String::from_utf8(raw_instructions.to_vec()).expect("Failed to decode instructions");

let instructions = match &kind {
ExampleKind::Standalone => {
let instructions_path = match metadata.instructions {
Some(instructions_file_name) => lang_path.join(instructions_file_name),
None => lang_path.join(default_instructions_file_name),
};

let raw_instructions = EXAMPLES
.get_file(instructions_path)
.expect("Failed to read instructions")
.contents();

String::from_utf8(raw_instructions.to_vec()).expect("Failed to decode instructions")
}
ExampleKind::ComposableAppCommon { .. } => "".to_string(),
ExampleKind::ComposableAppComponent { .. } => "".to_string(),
};

let name = ExampleName::from_string(example_root.file_name().unwrap().to_str().unwrap());

let mut wit_deps: Vec<PathBuf> = vec![];
Expand All @@ -459,20 +496,6 @@ fn parse_example(
wit_deps.push(Path::new("sockets").to_path_buf());
}

let kind = match (metadata.app_common_group, metadata.app_component_group) {
(None, None) => ExampleKind::Standalone,
(Some(group), None) => ExampleKind::ComposableAppCommon {
group: ComposableAppGroupName::from_string(group),
},
(None, Some(group)) => ExampleKind::ComposableAppComponent {
group: ComposableAppGroupName::from_string(group),
},
(Some(_), Some(_)) => panic!(
"Only one of appCommonGroup and appComponentGroup can be specified, example root: {}",
example_root.display()
),
};

let requires_adapter = metadata
.requires_adapter
.unwrap_or(metadata.adapter_target.is_some());
Expand Down
6 changes: 4 additions & 2 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use inflector::Inflector;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::fmt;
use std::fmt::Formatter;
use std::path::PathBuf;
use std::str::FromStr;
use std::{fmt, io};
use strum::IntoEnumIterator;
use strum_macros::EnumIter;

Expand Down Expand Up @@ -349,9 +349,11 @@ pub enum TargetExistsResolveMode {
MergeOrFail,
}

pub type MergeContents = Box<dyn FnOnce(&[u8]) -> io::Result<Vec<u8>>>;

pub enum TargetExistsResolveDecision {
Skip,
Merge(Box<dyn FnOnce(&str) -> String>),
Merge(MergeContents),
}

#[derive(Debug, Clone)]
Expand Down
28 changes: 21 additions & 7 deletions src/test/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
use std::io;
use std::path::PathBuf;
use std::process::exit;
use std::str::FromStr;

use clap::Parser;
use colored::{ColoredString, Colorize};
use golem_examples::model::{
Expand All @@ -15,6 +10,10 @@ use golem_examples::{
};
use nanoid::nanoid;
use regex::Regex;
use std::io;
use std::path::PathBuf;
use std::process::exit;
use std::str::FromStr;

#[derive(Parser, Debug)]
#[command()]
Expand Down Expand Up @@ -94,18 +93,27 @@ pub fn main() -> io::Result<()> {
let target_path = PathBuf::from(target_path.unwrap_or_else(|| "examples".to_string()))
.join("app-default");

if target_path.exists() {
println!("Deleting {}", target_path.display().to_string().blue());
std::fs::remove_dir_all(&target_path)?;
}

let app_examples = all_composable_app_examples();

for (language, examples) in app_examples {
println!("Testing language {}", language);
println!("Adding components for language {}", language.name().blue());

let default_examples = examples.get(&ComposableAppGroupName::default()).unwrap();
assert_eq!(default_examples.components.len(), 1);
let default_component_example = &default_examples.components[0];

for _ in 1..=4 {
let component_name = format!("app:comp-{}", nanoid!(10, &alphabet));
println!("Adding component {} ({})", component_name, language);
println!(
"Adding component {} ({})",
component_name.bright_blue(),
language.name().blue()
);
let package_name = PackageName::from_string(component_name).unwrap();
add_component_by_example(
default_examples.common.as_ref(),
Expand All @@ -116,6 +124,12 @@ pub fn main() -> io::Result<()> {
}
}

println!("Building with default profile");
std::process::Command::new("golem-cli")
.args(["app", "build"])
.current_dir(target_path)
.status()?;

Ok(())
}
}
Expand Down

0 comments on commit d52a81f

Please sign in to comment.