hv1 verify: add direct route (env JSON) and clean inline path; fix v1 phi incoming order; make test_runner use hv1 direct; add phase2037 phi canaries; load modules.workspace exports for alias; update docs (phase-20.38, source extensions) and CURRENT_TASK
This commit is contained in:
@ -6,5 +6,10 @@ pub enum UsingError {
|
||||
ReadToml(String),
|
||||
#[error("invalid nyash.toml format: {0}")]
|
||||
ParseToml(String),
|
||||
#[error("failed to read workspace module '{0}': {1}")]
|
||||
ReadWorkspaceModule(String, String),
|
||||
#[error("invalid workspace module '{0}': {1}")]
|
||||
ParseWorkspaceModule(String, String),
|
||||
#[error("workspace module '{0}' is missing module.name")]
|
||||
WorkspaceModuleMissingName(String),
|
||||
}
|
||||
|
||||
|
||||
@ -16,18 +16,35 @@ pub fn populate_from_toml(
|
||||
) -> Result<UsingPolicy, UsingError> {
|
||||
let mut policy = UsingPolicy::default();
|
||||
// Prefer CWD nyash.toml; if missing, honor NYASH_ROOT/nyash.toml for tools that run from subdirs
|
||||
let path = std::path::Path::new("nyash.toml");
|
||||
let text = if path.exists() {
|
||||
std::fs::read_to_string(path)
|
||||
} else if let Ok(root) = std::env::var("NYASH_ROOT") {
|
||||
let alt = std::path::Path::new(&root).join("nyash.toml");
|
||||
if alt.exists() { std::fs::read_to_string(alt) } else { return Ok(policy); }
|
||||
} else {
|
||||
return Ok(policy);
|
||||
}
|
||||
.map_err(|e| UsingError::ReadToml(e.to_string()))?;
|
||||
let (text, toml_path) = {
|
||||
let path = std::path::Path::new("nyash.toml");
|
||||
if path.exists() {
|
||||
(
|
||||
std::fs::read_to_string(path)
|
||||
.map_err(|e| UsingError::ReadToml(e.to_string()))?,
|
||||
path.to_path_buf(),
|
||||
)
|
||||
} else if let Ok(root) = std::env::var("NYASH_ROOT") {
|
||||
let alt = std::path::Path::new(&root).join("nyash.toml");
|
||||
if alt.exists() {
|
||||
(
|
||||
std::fs::read_to_string(&alt)
|
||||
.map_err(|e| UsingError::ReadToml(e.to_string()))?,
|
||||
alt,
|
||||
)
|
||||
} else {
|
||||
return Ok(policy);
|
||||
}
|
||||
} else {
|
||||
return Ok(policy);
|
||||
}
|
||||
};
|
||||
let doc = toml::from_str::<toml::Value>(&text)
|
||||
.map_err(|e| UsingError::ParseToml(e.to_string()))?;
|
||||
let toml_dir = toml_path
|
||||
.parent()
|
||||
.map(|p| p.to_path_buf())
|
||||
.unwrap_or_else(|| std::path::PathBuf::from("."));
|
||||
|
||||
// [modules] table flatten: supports nested namespaces (a.b.c = "path")
|
||||
if let Some(mods) = doc.get("modules").and_then(|v| v.as_table()) {
|
||||
@ -42,6 +59,9 @@ pub fn populate_from_toml(
|
||||
}
|
||||
}
|
||||
visit("", mods, pending_modules);
|
||||
if let Some(workspace_tbl) = mods.get("workspace").and_then(|v| v.as_table()) {
|
||||
load_workspace_modules(&toml_dir, workspace_tbl, pending_modules, aliases)?;
|
||||
}
|
||||
}
|
||||
|
||||
// [using.paths] array
|
||||
@ -93,3 +113,73 @@ pub fn populate_from_toml(
|
||||
|
||||
Ok(policy)
|
||||
}
|
||||
|
||||
fn load_workspace_modules(
|
||||
nyash_dir: &std::path::Path,
|
||||
workspace_tbl: &toml::value::Table,
|
||||
pending_modules: &mut Vec<(String, String)>,
|
||||
aliases: &mut HashMap<String, String>,
|
||||
) -> Result<(), UsingError> {
|
||||
let members = workspace_tbl
|
||||
.get("members")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or_else(|| UsingError::ParseWorkspaceModule("modules.workspace".into(), "expected members array".into()))?;
|
||||
|
||||
for entry in members {
|
||||
let raw_path = entry
|
||||
.as_str()
|
||||
.ok_or_else(|| UsingError::ParseWorkspaceModule("modules.workspace".into(), "members must be string paths".into()))?;
|
||||
let module_path = if std::path::Path::new(raw_path).is_absolute() {
|
||||
std::path::PathBuf::from(raw_path)
|
||||
} else {
|
||||
nyash_dir.join(raw_path)
|
||||
};
|
||||
let module_dir = module_path
|
||||
.parent()
|
||||
.map(|p| p.to_path_buf())
|
||||
.unwrap_or_else(|| nyash_dir.to_path_buf());
|
||||
let module_text = std::fs::read_to_string(&module_path).map_err(|e| {
|
||||
UsingError::ReadWorkspaceModule(module_path.to_string_lossy().to_string(), e.to_string())
|
||||
})?;
|
||||
let module_doc = toml::from_str::<toml::Value>(&module_text).map_err(|e| {
|
||||
UsingError::ParseWorkspaceModule(module_path.to_string_lossy().to_string(), e.to_string())
|
||||
})?;
|
||||
let module_name = module_doc
|
||||
.get("module")
|
||||
.and_then(|v| v.get("name"))
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or_else(|| {
|
||||
UsingError::WorkspaceModuleMissingName(module_path.to_string_lossy().to_string())
|
||||
})?;
|
||||
if let Some(exports_tbl) = module_doc.get("exports").and_then(|v| v.as_table()) {
|
||||
for (export_key, export_value) in exports_tbl {
|
||||
if let Some(rel_path) = export_value.as_str() {
|
||||
let mut full_name = module_name.to_string();
|
||||
if !export_key.is_empty() {
|
||||
full_name.push('.');
|
||||
full_name.push_str(export_key);
|
||||
}
|
||||
if pending_modules.iter().any(|(name, _)| name == &full_name) {
|
||||
continue;
|
||||
}
|
||||
let resolved_path = module_dir.join(rel_path);
|
||||
let resolved_str = resolved_path
|
||||
.canonicalize()
|
||||
.unwrap_or(resolved_path)
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
pending_modules.push((full_name, resolved_str));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(alias_tbl) = module_doc.get("aliases").and_then(|v| v.as_table()) {
|
||||
for (alias, target) in alias_tbl {
|
||||
if let Some(target_str) = target.as_str() {
|
||||
aliases.insert(alias.to_string(), target_str.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user