///|
#borrow(project_root, log_path)
extern "C" fn validate_generated_project_stage_native(
project_root : Bytes,
log_path : Bytes,
stage : Int,
append : Int,
) -> Int = "moui_cli_validate_generated_project_stage"
///|
fn project_validation_stage(code : Int) -> String {
match code % 100 {
1 => "moon update"
2 => "moon check --target all --warn-list +73"
3 => "moon info --target all"
_ => "project validation"
}
}
///|
fn run_generated_project_validation_stage(
project_root : String,
log_path : String,
stage : Int,
) -> Result[Unit, String] {
let code = validate_generated_project_stage_native(
nul_terminated(project_root),
nul_terminated(log_path),
stage,
if stage == 1 {
0
} else {
1
},
)
if code == 0 {
Ok(())
} else {
let log = @fs.read_file_to_string(log_path) catch {
_ => "validation log could not be read"
}
Err(
project_validation_stage(code) +
(if code >= 100 { " could not be started" } else { " failed" }) +
":\n" +
log,
)
}
}
///|
fn stage_local_validation_package(
project_root : String,
source_root : String,
package_name : String,
) -> Result[Unit, String] {
if !path_is_dir(source_root) ||
!path_is_nonempty_file(join_path(source_root, "moon.mod")) {
return Err("local validation package is incomplete: " + source_root)
}
let files = match collect_template_files(source_root) {
Ok(value) => value
Err(message) => return Err(message)
}
let destination = join_path(
project_root,
".mooncakes/wzzc-dev/" + package_name,
)
remove_tree(destination)
write_file_plan_atomic(destination, files)
}
///|
fn stage_local_moui_validation_override(
project_root : String,
) -> Result[Unit, String] {
match @env.get_env_var("MOUI_PACKAGE_ROOT") {
None | Some("") => Ok(())
Some(root) => {
match stage_local_validation_package(project_root, root, "moui") {
Ok(_) => ()
Err(message) => return Err(message)
}
let parent = parent_dir(root)
for
entry in [
("MOUI_SKIA_ROOT", "moui_skia", "moui_skia"),
("MOUI_SUN_ROOT", "moui_sun", "moui_sun"),
] {
let (environment, sibling, package_name) = entry
let candidate = @env.get_env_var(environment).unwrap_or(
join_path(parent, sibling),
)
if path_is_dir(candidate) {
match
stage_local_validation_package(
project_root, candidate, package_name,
) {
Ok(_) => ()
Err(message) => return Err(message)
}
}
}
Ok(())
}
}
}
///|
fn validate_generated_project(project_root : String) -> Result[Unit, String] {
let log_path = join_path(project_root, ".moui-validation.log")
match run_generated_project_validation_stage(project_root, log_path, 1) {
Ok(_) => ()
Err(message) => return Err(message)
}
match stage_local_moui_validation_override(project_root) {
Ok(_) => ()
Err(message) => return Err(message)
}
for stage in [2, 3] {
match
run_generated_project_validation_stage(project_root, log_path, stage) {
Ok(_) => ()
Err(message) => return Err(message)
}
}
@fs.remove_file(log_path) catch {
_ => ()
}
Ok(())
}
///|
fn cleanup_generated_project_validation(project_root : String) -> Unit {
for name in [".moui-validation.log", ".mooncakes", "_build"] {
remove_tree(join_path(project_root, name))
}
}
///|
fn write_validated_project_file_plan(
target : String,
files : Array[PlannedFile],
validate : (String) -> Result[Unit, String],
) -> Result[Array[String], String] {
let temp = match stage_file_plan(target, files) {
Ok(value) => value
Err(message) => return Err(message)
}
match validate(temp) {
Err(message) => {
remove_tree(temp)
return Err(message)
}
Ok(_) => ()
}
cleanup_generated_project_validation(temp)
let validated_files = match collect_template_files(temp) {
Ok(value) => value
Err(message) => {
remove_tree(temp)
return Err(message)
}
}
match commit_staged_file_plan(temp, target) {
Ok(_) => Ok(validated_files.map(file => file.path))
Err(message) => Err(message)
}
}