Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Use std::path and canonicalization for the paths in Choo #106

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
10 changes: 9 additions & 1 deletion Cargo.lock

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

94 changes: 57 additions & 37 deletions apps/choo/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use sword::noun::{Atom, D, T};
use sword_macros::tas;
use tokio::fs::File;
use tokio::io::AsyncReadExt;
use tracing::error;
use walkdir::{DirEntry, WalkDir};

use clap::{arg, command, ColorChoice, Parser};
Expand All @@ -29,10 +28,10 @@ struct ChooCli {
boot: BootCli,

#[arg(help = "Path to file to compile")]
entry: String,
entry: std::path::PathBuf,

#[arg(help = "Path to root of dependency directory", default_value = "hoon")]
directory: String,
directory: std::path::PathBuf,

#[arg(
long,
Expand Down Expand Up @@ -67,7 +66,7 @@ async fn main() -> Result<(), Error> {
let cli = ChooCli::parse();
let result = std::panic::AssertUnwindSafe(async {
let nockapp = initialize_nockapp(cli).await?;
work_loop(nockapp).await;
nockapp.work_loop().await?;
Ok::<(), Error>(())
})
.catch_unwind()
Expand All @@ -91,10 +90,18 @@ async fn main() -> Result<(), Error> {
Ok(())
}

async fn initialize_nockapp(cli: ChooCli) -> Result<crown::nockapp::NockApp, Error> {
// Remove trailing slash from directory if present
let directory = cli.directory.trim_end_matches('/').to_string();
fn canonicalize_and_string(path: &std::path::Path) -> Result<String, Error> {
let path = path.canonicalize()?;
let path = path.to_str().ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
"Path is not valid or file cannot be found",
)
})?;
Ok(path.to_string())
}

async fn initialize_nockapp(cli: ChooCli) -> Result<crown::nockapp::NockApp, Error> {
let mut nockapp = boot::setup(KERNEL_JAM, Some(cli.boot.clone()), &[], "choo")?;
boot::init_default_tracing(&cli.boot.clone());
let mut slab = NounSlab::new();
Expand All @@ -114,18 +121,11 @@ async fn initialize_nockapp(cli: ChooCli) -> Result<crown::nockapp::NockApp, Err
Atom::from_value(&mut slab, contents_vec).unwrap().as_noun()
};

let mut entry = cli.entry.clone();

// Insert a leading slash if it is not present
// Needed to make the entry path an actual hoon $path type
if !entry.starts_with('/') {
entry.insert(0, '/');
}

// hoon does not support uppercase paths
let entry_path = Atom::from_value(&mut slab, entry.to_lowercase()).unwrap().as_noun();
let entry_string = canonicalize_and_string(&cli.entry)?;
let entry_path = Atom::from_value(&mut slab, entry_string.to_lowercase()).unwrap().as_noun();

let mut directory_noun = D(0);
let directory = canonicalize_and_string(&cli.directory)?;

let walker = WalkDir::new(&directory)
.follow_links(true)
Expand Down Expand Up @@ -169,37 +169,44 @@ async fn initialize_nockapp(cli: ChooCli) -> Result<crown::nockapp::NockApp, Err
Ok(nockapp)
}

async fn work_loop(mut nockapp: crown::nockapp::NockApp) {
loop {
let work_res = nockapp.work().await;
if let Err(e) = work_res {
error!("work error: {:?}", e);
break;
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
use tokio::fs;
use tracing::info;

#[ignore]
#[test]
fn test_result() -> Result<(), Box<dyn std::error::Error>> {
let result: Result<(), Box<dyn std::error::Error>> = Err(Box::new(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Path is not valid or file cannot be found",
)));
result
}

// TODO: Move this to an integration test.
#[tokio::test]
async fn test_compile_test_app() -> Result<(), Box<dyn std::error::Error>> {
let mut test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
// let mut test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
// test_dir.pop();
// test_dir.push("test-app");

// use std::path to get pwd() and then canonicalize
let pwd = std::env::current_dir().unwrap();
let mut test_dir = pwd.clone();
test_dir.pop();
test_dir.push("test-app");

let entry = test_dir.join("bootstrap/kernel.hoon");

// TODO: Add -o flag to specify output file and then use the tmp-dir
// TODO: instead of mutating the non-tmp filesystem in this test
// Clean up any existing output file
let _ = fs::remove_file("out.jam").await;

let mut deps_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let mut deps_dir = pwd.clone();
deps_dir.pop();
deps_dir.push("hoon-deps");
let entry = format!("{}/bootstrap/kernel.hoon", test_dir.display());

let result = async {
let cli = ChooCli {
Expand All @@ -212,15 +219,15 @@ mod tests {
state_jam: None,
},
entry: entry.clone(),
directory: deps_dir.display().to_string(),
directory: deps_dir.clone(),
arbitrary: false,
};

let nockapp = initialize_nockapp(cli).await?;
info!("Test directory: {}", test_dir.display());
info!("Dependencies directory: {}", deps_dir.display());
info!("Entry file: {}", entry.clone());
work_loop(nockapp).await;
info!("Test directory: {:?}", test_dir);
info!("Dependencies directory: {:?}", deps_dir);
info!("Entry file: {:?}", entry);
nockapp.work_loop().await.expect("Work loop failed");

// TODO this doesn't work because choo exits when compilation is done.
// Verify output file exists and is not empty
Expand All @@ -235,4 +242,17 @@ mod tests {

result
}

#[test]
#[cfg_attr(miri, ignore)]
fn test_canonicalize_and_string() {
let path = std::path::Path::new("Cargo.toml");
let result = super::canonicalize_and_string(path);
assert!(result.is_ok());
// left: "/Users/callen/work/zorp/nockapp/apps/choo/Cargo.toml"
// right: "Cargo.toml"
let pwd = std::env::current_dir().unwrap();
let cargo_toml = pwd.join("Cargo.toml").canonicalize().unwrap();
assert_eq!(result.unwrap(), cargo_toml.to_str().unwrap());
}
}
2 changes: 1 addition & 1 deletion crown/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ tracing = { workspace = true }
tracing-test = { workspace = true }
tracing-subscriber = { workspace = true }
tokio = { workspace = true, features = ["time", "sync", "signal"]}
tokio-util = { workspace = true }
tokio-util = { workspace = true, features = ["rt"] }
yaque = { workspace = true }

[lib]
Expand Down
3 changes: 3 additions & 0 deletions crown/src/nockapp/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use super::driver::IOAction;
/// Error type for NockApps
#[derive(Debug, Error)]
pub enum NockAppError {
/// NockApp exited with a code, shouldn't ever be 0, that's a Done/Success.
#[error("NockApp exited with error code: {0}")]
Exit(usize),
#[error("Timeout")]
Timeout,
#[error("IO error: {0}")]
Expand Down
Loading