diff --git a/Cargo.lock b/Cargo.lock index 30d6dc4a..870af210 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4708,6 +4708,7 @@ dependencies = [ "veryl-formatter", "veryl-metadata", "veryl-parser", + "veryl-path", "veryl-sourcemap", ] @@ -4764,21 +4765,18 @@ dependencies = [ "veryl-formatter", "veryl-metadata", "veryl-parser", + "veryl-path", ] [[package]] name = "veryl-metadata" version = "0.12.0" dependencies = [ - "directories", - "fs4", "git-repository", "log", - "merkle_hash", "miette", "once_cell", "regex", - "rust-embed", "semver 1.0.23", "serde", "serde_regex", @@ -4789,7 +4787,8 @@ dependencies = [ "url", "uuid", "veryl-parser", - "walkdir", + "veryl-path", + "veryl-std", ] [[package]] @@ -4805,6 +4804,17 @@ dependencies = [ "paste", "regex", "thiserror", +] + +[[package]] +name = "veryl-path" +version = "0.12.0" +dependencies = [ + "directories", + "fs4", + "log", + "miette", + "thiserror", "walkdir", ] @@ -4818,6 +4828,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "veryl-std" +version = "0.12.0" +dependencies = [ + "merkle_hash", + "miette", + "rust-embed", + "thiserror", + "veryl-path", +] + [[package]] name = "veryl-tests" version = "0.1.0" @@ -4829,6 +4850,7 @@ dependencies = [ "veryl-formatter", "veryl-metadata", "veryl-parser", + "veryl-path", "walkdir", ] diff --git a/Cargo.toml b/Cargo.toml index 575a3006..e80cf09a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,9 @@ members = [ "crates/mdbook", "crates/metadata", "crates/parser", + "crates/path", "crates/sourcemap", + "crates/std", "crates/tests", "crates/veryl", ] @@ -45,6 +47,7 @@ thiserror = "1.0" tokio = {version = "1.40.0", features = ["full"]} toml = "0.8.19" url = {version = "2.5", features = ["serde"]} +walkdir = "2.5.0" [workspace.metadata.release] tag = false diff --git a/crates/languageserver/Cargo.toml b/crates/languageserver/Cargo.toml index 2daf2cd3..1073676b 100644 --- a/crates/languageserver/Cargo.toml +++ b/crates/languageserver/Cargo.toml @@ -28,3 +28,4 @@ veryl-analyzer = {version = "0.12.0", path = "../analyzer"} veryl-formatter = {version = "0.12.0", path = "../formatter"} veryl-metadata = {version = "0.12.0", path = "../metadata"} veryl-parser = {version = "0.12.0", path = "../parser"} +veryl-path = {version = "0.12.0", path = "../path"} diff --git a/crates/languageserver/src/server.rs b/crates/languageserver/src/server.rs index 51ade823..a5c9a15b 100644 --- a/crates/languageserver/src/server.rs +++ b/crates/languageserver/src/server.rs @@ -12,10 +12,11 @@ use veryl_analyzer::symbol::SymbolKind as VerylSymbolKind; use veryl_analyzer::symbol_path::SymbolPath; use veryl_analyzer::{namespace_table, symbol_table, Analyzer, AnalyzerError}; use veryl_formatter::Formatter; -use veryl_metadata::{Metadata, PathPair}; +use veryl_metadata::Metadata; use veryl_parser::veryl_token::Token; use veryl_parser::veryl_walker::VerylWalker; use veryl_parser::{resource_table, Finder, Parser, ParserError}; +use veryl_path::PathPair; pub enum MsgToServer { DidOpen { @@ -119,7 +120,7 @@ impl Server { document_map: DashMap::new(), parser_map: DashMap::new(), metadata_map: DashMap::new(), - cache_dir: Metadata::cache_path(), + cache_dir: veryl_path::cache_path(), lsp_token: 0, background_tasks: VecDeque::new(), background_done: true, diff --git a/crates/metadata/Cargo.toml b/crates/metadata/Cargo.toml index 1beff800..5941ec11 100644 --- a/crates/metadata/Cargo.toml +++ b/crates/metadata/Cargo.toml @@ -13,12 +13,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -directories = "5.0" git-repository = {version = "0.35.0", optional = true, features = ["blocking-network-client", "blocking-http-transport-reqwest", "blocking-http-transport-reqwest-rust-tls"]} log = {workspace = true} once_cell = {workspace = true} regex = {workspace = true} -rust-embed = {version = "8.5", features = ["debug-embed", "compression", "include-exclude"]} semver = {workspace = true} serde = {workspace = true} serde_regex = "1.1" @@ -28,21 +26,18 @@ toml = {workspace = true} url = {workspace = true} uuid = {version = "1.10", default-features = false, features = ["v5", "serde"]} veryl-parser = {version = "0.12.0", path = "../parser"} -walkdir = "2.5.0" +veryl-path = {version = "0.12.0", path = "../path"} +veryl-std = {version = "0.12.0", path = "../std"} [target.'cfg(target_family = "wasm")'.dependencies] miette = {workspace = true, features = ["fancy-no-syscall"]} [target.'cfg(not(target_family = "wasm"))'.dependencies] miette = {workspace = true, features = ["fancy"]} -fs4 = {version = "0.9.1", features = ["sync"]} [dev-dependencies] tempfile = {workspace = true} -[build-dependencies] -merkle_hash = "3.7" - [features] default = ["git-command"] git-command = [] diff --git a/crates/metadata/src/lib.rs b/crates/metadata/src/lib.rs index 4cc0f86f..5142e890 100644 --- a/crates/metadata/src/lib.rs +++ b/crates/metadata/src/lib.rs @@ -9,17 +9,15 @@ mod metadata_error; mod project; mod pubfile; mod publish; -mod stdlib; mod test; #[cfg(test)] mod tests; -mod utils; pub use build::{Build, BuiltinType, ClockType, FilelistType, ResetType, SourceMapTarget, Target}; pub use doc::Doc; pub use format::Format; pub use lint::{Case, Lint}; pub use lockfile::Lockfile; -pub use metadata::{BumpKind, Metadata, PathPair}; +pub use metadata::{BumpKind, Metadata}; pub use metadata_error::MetadataError; pub use project::Project; pub use pubfile::{Pubfile, Release}; diff --git a/crates/metadata/src/lockfile.rs b/crates/metadata/src/lockfile.rs index c56bfdd3..38572146 100644 --- a/crates/metadata/src/lockfile.rs +++ b/crates/metadata/src/lockfile.rs @@ -2,7 +2,6 @@ use crate::git::Git; use crate::metadata::{Dependency, Metadata}; use crate::metadata_error::MetadataError; use crate::pubfile::{Pubfile, Release}; -use crate::{utils, PathPair}; use log::info; use semver::{Version, VersionReq}; use serde::{Deserialize, Serialize}; @@ -12,6 +11,7 @@ use std::path::Path; use std::str::FromStr; use url::Url; use uuid::Uuid; +use veryl_path::PathPair; #[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(deny_unknown_fields)] @@ -160,7 +160,7 @@ impl Lockfile { let metadata = self.get_metadata(&lock.url, &lock.revision)?; let path = metadata.project_path(); - for src in &utils::gather_files_with_extension(&path, "veryl", false)? { + for src in &veryl_path::gather_files_with_extension(&path, "veryl", false)? { let rel = src.strip_prefix(&path)?; let mut dst = base_dst.join(&lock.name); dst.push(rel); @@ -334,7 +334,7 @@ impl Lockfile { url: &Url, version_req: &VersionReq, ) -> Result { - let resolve_dir = Metadata::cache_path().join("resolve"); + let resolve_dir = veryl_path::cache_path().join("resolve"); if !resolve_dir.exists() { fs::create_dir_all(&resolve_dir)?; @@ -343,11 +343,11 @@ impl Lockfile { let uuid = Self::gen_uuid(url, "")?; let path = resolve_dir.join(uuid.simple().encode_lower(&mut Uuid::encode_buffer())); - let lock = utils::lock_dir("resolve")?; + let lock = veryl_path::lock_dir("resolve")?; let git = Git::clone(url, &path)?; git.fetch()?; git.checkout(None)?; - utils::unlock_dir(lock)?; + veryl_path::unlock_dir(lock)?; let toml = path.join("Veryl.pub"); let mut pubfile = Pubfile::load(toml)?; @@ -367,7 +367,7 @@ impl Lockfile { } fn get_metadata(&self, url: &Url, revision: &str) -> Result { - let dependencies_dir = Metadata::cache_path().join("dependencies"); + let dependencies_dir = veryl_path::cache_path().join("dependencies"); if !dependencies_dir.exists() { fs::create_dir_all(&dependencies_dir)?; @@ -379,23 +379,23 @@ impl Lockfile { let toml = path.join("Veryl.toml"); if !path.exists() { - let lock = utils::lock_dir("dependencies")?; + let lock = veryl_path::lock_dir("dependencies")?; let git = Git::clone(url, &path)?; git.fetch()?; git.checkout(Some(revision))?; - utils::unlock_dir(lock)?; + veryl_path::unlock_dir(lock)?; } else { let git = Git::open(&path)?; let ret = git.is_clean().map_or(false, |x| x); // If the existing path is not git repository, cleanup and re-try if !ret || !toml.exists() { - let lock = utils::lock_dir("dependencies")?; + let lock = veryl_path::lock_dir("dependencies")?; fs::remove_dir_all(&path)?; let git = Git::clone(url, &path)?; git.fetch()?; git.checkout(Some(revision))?; - utils::unlock_dir(lock)?; + veryl_path::unlock_dir(lock)?; } } diff --git a/crates/metadata/src/metadata.rs b/crates/metadata/src/metadata.rs index 5eba38eb..ba8a25ed 100644 --- a/crates/metadata/src/metadata.rs +++ b/crates/metadata/src/metadata.rs @@ -7,10 +7,8 @@ use crate::lockfile::Lockfile; use crate::project::Project; use crate::pubfile::{Pubfile, Release}; use crate::publish::Publish; -use crate::stdlib; use crate::test::Test; -use crate::{utils, FilelistType, MetadataError}; -use directories::ProjectDirs; +use crate::{FilelistType, MetadataError}; use log::{debug, info}; use once_cell::sync::Lazy; use regex::Regex; @@ -23,13 +21,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::str::FromStr; use url::Url; - -#[derive(Clone, Debug)] -pub struct PathPair { - pub prj: String, - pub src: PathBuf, - pub dst: PathBuf, -} +use veryl_path::PathPair; #[derive(Clone, Copy, Debug)] pub enum BumpKind { @@ -231,7 +223,7 @@ impl Metadata { let base = self.project_path(); let src_files = if files.is_empty() { - utils::gather_files_with_extension(&base, "veryl", symlink)? + veryl_path::gather_files_with_extension(&base, "veryl", symlink)? } else { let mut ret = Vec::new(); for file in files { @@ -264,8 +256,8 @@ impl Metadata { } if !self.build.exclude_std { - stdlib::expand()?; - ret.append(&mut stdlib::paths(&base_dst)?); + veryl_std::expand()?; + ret.append(&mut veryl_std::paths(&base_dst)?); } self.update_lockfile()?; @@ -288,11 +280,6 @@ version = "0.1.0""### )) } - pub fn cache_path() -> PathBuf { - let project_dir = ProjectDirs::from("org", "veryl-lang", "veryl").unwrap(); - project_dir.cache_dir().to_path_buf() - } - pub fn project_path(&self) -> PathBuf { self.metadata_path.parent().unwrap().to_path_buf() } diff --git a/crates/metadata/src/metadata_error.rs b/crates/metadata/src/metadata_error.rs index af29538d..e050a9ec 100644 --- a/crates/metadata/src/metadata_error.rs +++ b/crates/metadata/src/metadata_error.rs @@ -3,6 +3,7 @@ use semver::Version; use std::path::PathBuf; use thiserror::Error; use url::Url; +use veryl_path::PathError; #[derive(Error, Diagnostic, Debug)] pub enum MetadataError { @@ -18,10 +19,6 @@ pub enum MetadataError { #[error("toml load failed")] Deserialize(#[from] toml::de::Error), - #[diagnostic(code(MetadataError::Walkdir), help(""))] - #[error("walkdir error")] - Walkdir(#[from] walkdir::Error), - #[diagnostic(code(MetadataError::StripPrefix), help(""))] #[error("strip prefix error")] StripPrefix(#[from] std::path::StripPrefixError), @@ -67,4 +64,8 @@ pub enum MetadataError { #[diagnostic(code(MetadataError::NameConflict), help(""))] #[error("project name \"{0}\" is used multiply in dependencies")] NameConflict(String), + + #[diagnostic(code(MetadataError::Path), help(""))] + #[error("path error")] + Path(#[from] PathError), } diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index 4284c247..4bd18967 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -31,4 +31,3 @@ miette = {workspace = true, features = ["fancy"]} [build-dependencies] parol = "0.31.0" parol_runtime = {version = "0.24.1", features = ["auto_generation"]} -walkdir = "2.5.0" diff --git a/crates/path/Cargo.toml b/crates/path/Cargo.toml new file mode 100644 index 00000000..8d836301 --- /dev/null +++ b/crates/path/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "veryl-path" +version = "0.12.0" +authors.workspace = true +repository.workspace = true +keywords.workspace = true +categories.workspace = true +license.workspace = true +readme.workspace = true +description.workspace = true +edition = "2021" + +[dependencies] +directories = "5.0" +log = {workspace = true} +thiserror = {workspace = true} +walkdir = {workspace = true} + +[target.'cfg(target_family = "wasm")'.dependencies] +miette = {workspace = true, features = ["fancy-no-syscall"]} + +[target.'cfg(not(target_family = "wasm"))'.dependencies] +miette = {workspace = true, features = ["fancy"]} +fs4 = {version = "0.9.1", features = ["sync"]} diff --git a/crates/metadata/src/utils.rs b/crates/path/src/lib.rs similarity index 73% rename from crates/metadata/src/utils.rs rename to crates/path/src/lib.rs index 74074e4f..befcfe72 100644 --- a/crates/metadata/src/utils.rs +++ b/crates/path/src/lib.rs @@ -1,5 +1,4 @@ -use crate::metadata::Metadata; -use crate::MetadataError; +use directories::ProjectDirs; #[cfg(not(target_family = "wasm"))] use fs4::fs_std::FileExt; use log::debug; @@ -8,11 +7,26 @@ use std::fs::File; use std::path::{Path, PathBuf}; use walkdir::WalkDir; +mod path_error; +pub use path_error::PathError; + +#[derive(Clone, Debug)] +pub struct PathPair { + pub prj: String, + pub src: PathBuf, + pub dst: PathBuf, +} + +pub fn cache_path() -> PathBuf { + let project_dir = ProjectDirs::from("org", "veryl-lang", "veryl").unwrap(); + project_dir.cache_dir().to_path_buf() +} + pub fn gather_files_with_extension>( base_dir: T, ext: &str, symlink: bool, -) -> Result, MetadataError> { +) -> Result, PathError> { let mut inner_prj = Vec::new(); for entry in WalkDir::new(base_dir.as_ref()) .follow_links(symlink) @@ -55,8 +69,8 @@ pub fn gather_files_with_extension>( } #[cfg(not(target_family = "wasm"))] -pub fn lock_dir>(path: T) -> Result { - let base_dir = Metadata::cache_path().join(path); +pub fn lock_dir>(path: T) -> Result { + let base_dir = cache_path().join(path); let lock = base_dir.join("lock"); let lock = File::create(lock)?; lock.lock_exclusive()?; @@ -64,17 +78,17 @@ pub fn lock_dir>(path: T) -> Result { } #[cfg(not(target_family = "wasm"))] -pub fn unlock_dir(lock: File) -> Result<(), MetadataError> { +pub fn unlock_dir(lock: File) -> Result<(), PathError> { lock.unlock()?; Ok(()) } #[cfg(target_family = "wasm")] -pub fn lock_dir>(_path: T) -> Result<(), MetadataError> { +pub fn lock_dir>(_path: T) -> Result<(), PathError> { Ok(()) } #[cfg(target_family = "wasm")] -pub fn unlock_dir(_lock: ()) -> Result<(), MetadataError> { +pub fn unlock_dir(_lock: ()) -> Result<(), PathError> { Ok(()) } diff --git a/crates/path/src/path_error.rs b/crates/path/src/path_error.rs new file mode 100644 index 00000000..68c9fd60 --- /dev/null +++ b/crates/path/src/path_error.rs @@ -0,0 +1,13 @@ +use miette::{self, Diagnostic}; +use thiserror::Error; + +#[derive(Error, Diagnostic, Debug)] +pub enum PathError { + #[diagnostic(code(PathError::FileIO), help(""))] + #[error("file I/O error")] + FileIO(#[from] std::io::Error), + + #[diagnostic(code(PathError::StripPrefix), help(""))] + #[error("strip prefix error")] + StripPrefix(#[from] std::path::StripPrefixError), +} diff --git a/crates/std/Cargo.toml b/crates/std/Cargo.toml new file mode 100644 index 00000000..f0cc1756 --- /dev/null +++ b/crates/std/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "veryl-std" +version = "0.12.0" +authors.workspace = true +repository.workspace = true +keywords.workspace = true +categories.workspace = true +license.workspace = true +readme.workspace = true +description.workspace = true +edition = "2021" + +[dependencies] +miette = {workspace = true} +rust-embed = {version = "8.5", features = ["debug-embed", "compression", "include-exclude"]} +thiserror = {workspace = true} +veryl-path = {version = "0.12.0", path = "../path"} + +[build-dependencies] +merkle_hash = "3.7" diff --git a/crates/metadata/build.rs b/crates/std/build.rs similarity index 80% rename from crates/metadata/build.rs rename to crates/std/build.rs index 45173808..df82db89 100644 --- a/crates/metadata/build.rs +++ b/crates/std/build.rs @@ -4,7 +4,7 @@ use std::fs; use std::path::Path; fn main() { - let tree = MerkleTree::builder("./std/src") + let tree = MerkleTree::builder("../metadata/std/src") .algorithm(Algorithm::Blake3) .hash_names(true) .build() @@ -24,5 +24,5 @@ fn main() { ), ) .unwrap(); - println!("cargo::rerun-if-changed=./std/src"); + println!("cargo::rerun-if-changed=../metadata/std/src"); } diff --git a/crates/metadata/src/stdlib.rs b/crates/std/src/lib.rs similarity index 69% rename from crates/metadata/src/stdlib.rs rename to crates/std/src/lib.rs index bbe254b9..5096cd55 100644 --- a/crates/metadata/src/stdlib.rs +++ b/crates/std/src/lib.rs @@ -1,28 +1,26 @@ -use crate::metadata::Metadata; -use crate::metadata_error::MetadataError; -use crate::{utils, PathPair}; use rust_embed::Embed; use std::fs; use std::path::{Path, PathBuf}; +use veryl_path::{PathError, PathPair}; include!(concat!(env!("OUT_DIR"), "/std_hash.rs")); #[derive(Embed)] -#[folder = "./std/src"] +#[folder = "../metadata/std/src"] #[include = "*.veryl"] struct Asset; fn std_dir() -> PathBuf { - Metadata::cache_path().join("std").join(STD_HASH) + veryl_path::cache_path().join("std").join(STD_HASH) } -pub fn expand() -> Result<(), MetadataError> { +pub fn expand() -> Result<(), PathError> { let std_dir = std_dir(); if !std_dir.exists() { fs::create_dir_all(&std_dir)?; - let lock = utils::lock_dir(&std_dir)?; + let lock = veryl_path::lock_dir(&std_dir)?; for file in Asset::iter() { let content = Asset::get(file.as_ref()).unwrap(); @@ -36,17 +34,17 @@ pub fn expand() -> Result<(), MetadataError> { fs::write(&path, content.data.as_ref())?; } - utils::unlock_dir(lock)?; + veryl_path::unlock_dir(lock)?; } Ok(()) } -pub fn paths(base_dst: &Path) -> Result, MetadataError> { +pub fn paths(base_dst: &Path) -> Result, PathError> { let mut ret = Vec::new(); let std_dir = std_dir().canonicalize().unwrap(); - for src in &utils::gather_files_with_extension(&std_dir, "veryl", false)? { + for src in &veryl_path::gather_files_with_extension(&std_dir, "veryl", false)? { let rel = src.strip_prefix(&std_dir)?; let mut dst = base_dst.join("std"); dst.push(rel); diff --git a/crates/tests/Cargo.toml b/crates/tests/Cargo.toml index 5bcaa7dd..c5e40992 100644 --- a/crates/tests/Cargo.toml +++ b/crates/tests/Cargo.toml @@ -11,6 +11,7 @@ veryl-emitter = {version = "0.12.0", path = "../emitter"} veryl-formatter = {version = "0.12.0", path = "../formatter"} veryl-metadata = {version = "0.12.0", path = "../metadata"} veryl-parser = {version = "0.12.0", path = "../parser"} +veryl-path = {version = "0.12.0", path = "../path"} [dev-dependencies] criterion = "0.5.1" @@ -19,7 +20,7 @@ criterion = "0.5.1" pprof = {version = "0.13.0", features = ["flamegraph"]} [build-dependencies] -walkdir = "2.5.0" +walkdir = {workspace = true} [[bench]] name = "benchmark" diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs index 83b9e665..47b4682d 100644 --- a/crates/tests/src/lib.rs +++ b/crates/tests/src/lib.rs @@ -32,7 +32,7 @@ mod analyzer { if crate::DEPENDENCY_TESTS.contains(&name) { let paths = metadata.paths::<&str>(&[], false).unwrap(); - let cache_path = Metadata::cache_path().canonicalize().unwrap(); + let cache_path = veryl_path::cache_path().canonicalize().unwrap(); for path in paths { if path.src.starts_with(&cache_path) { let input = fs::read_to_string(&path.src).unwrap(); @@ -115,7 +115,7 @@ mod emitter { if crate::DEPENDENCY_TESTS.contains(&name) { let paths = metadata.paths::<&str>(&[], false).unwrap(); - let cache_path = Metadata::cache_path().canonicalize().unwrap(); + let cache_path = veryl_path::cache_path().canonicalize().unwrap(); for path in paths { if path.src.starts_with(&cache_path) { let input = fs::read_to_string(&path.src).unwrap(); diff --git a/crates/veryl/Cargo.toml b/crates/veryl/Cargo.toml index 47614ea8..55aeb5cf 100644 --- a/crates/veryl/Cargo.toml +++ b/crates/veryl/Cargo.toml @@ -49,4 +49,5 @@ veryl-emitter = {version = "0.12.0", path = "../emitter"} veryl-formatter = {version = "0.12.0", path = "../formatter"} veryl-metadata = {version = "0.12.0", path = "../metadata"} veryl-parser = {version = "0.12.0", path = "../parser"} +veryl-path = {version = "0.12.0", path = "../path"} veryl-sourcemap = {version = "0.12.0", path = "../sourcemap"} diff --git a/crates/veryl/src/cmd_build.rs b/crates/veryl/src/cmd_build.rs index b5e3cf42..6ea01a31 100644 --- a/crates/veryl/src/cmd_build.rs +++ b/crates/veryl/src/cmd_build.rs @@ -12,8 +12,9 @@ use veryl_analyzer::namespace::Namespace; use veryl_analyzer::symbol::SymbolKind; use veryl_analyzer::{type_dag, Analyzer}; use veryl_emitter::Emitter; -use veryl_metadata::{FilelistType, Metadata, PathPair, SourceMapTarget, Target}; +use veryl_metadata::{FilelistType, Metadata, SourceMapTarget, Target}; use veryl_parser::{resource_table, veryl_token::TokenSource, Parser}; +use veryl_path::PathPair; pub struct CmdBuild { opt: OptBuild,