From 37f150b7e7a5ec9b67c5528600a86a96931fdbb8 Mon Sep 17 00:00:00 2001 From: Jaap Frolich Date: Sun, 9 Jul 2023 22:14:13 +0200 Subject: [PATCH] :recycle: - Use relative paths --- src/bsconfig.rs | 21 ++++++-- src/build.rs | 14 +++-- src/clean.rs | 58 ++++++++++---------- src/helpers.rs | 31 ++--------- src/package_tree.rs | 126 ++++++++++++++++++++++---------------------- 5 files changed, 118 insertions(+), 132 deletions(-) diff --git a/src/bsconfig.rs b/src/bsconfig.rs index 2d1576b..46222cc 100644 --- a/src/bsconfig.rs +++ b/src/bsconfig.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use std::path::{Path, PathBuf}; use std::{fmt, fs}; #[derive(Deserialize, Debug, Clone)] @@ -27,10 +28,14 @@ pub struct PackageSource { /// `to_qualified_without_children` takes a tree like structure of dependencies, coming in from /// `bsconfig`, and turns it into a flat list. The main thing we extract here are the source /// folders, and optional subdirs, where potentially, the subdirs recurse or not. -pub fn to_qualified_without_children(s: &Source) -> PackageSource { +pub fn to_qualified_without_children(s: &Source, sub_path: Option) -> PackageSource { match s { Source::Shorthand(dir) => PackageSource { - dir: dir.to_owned(), + dir: sub_path + .map(|p| p.join(Path::new(dir))) + .unwrap_or(Path::new(dir).to_path_buf()) + .to_string_lossy() + .to_string(), subdirs: None, type_: None, }, @@ -39,12 +44,20 @@ pub fn to_qualified_without_children(s: &Source) -> PackageSource { type_, subdirs: Some(Subdirs::Recurse(should_recurse)), }) => PackageSource { - dir: dir.to_owned(), + dir: sub_path + .map(|p| p.join(Path::new(dir))) + .unwrap_or(Path::new(dir).to_path_buf()) + .to_string_lossy() + .to_string(), subdirs: Some(Subdirs::Recurse(*should_recurse)), type_: type_.to_owned(), }, Source::Qualified(PackageSource { dir, type_, .. }) => PackageSource { - dir: dir.to_owned(), + dir: sub_path + .map(|p| p.join(Path::new(dir))) + .unwrap_or(Path::new(dir).to_path_buf()) + .to_string_lossy() + .to_string(), subdirs: None, type_: type_.to_owned(), }, diff --git a/src/build.rs b/src/build.rs index 77df50c..bc2131b 100644 --- a/src/build.rs +++ b/src/build.rs @@ -173,7 +173,8 @@ fn generate_ast( let uncurried_args = get_uncurried_args(version, &package, &root_package); let bsc_flags = bsconfig::flatten_flags(&package.bsconfig.bsc_flags); - let res_to_ast_args = |file: String| -> Vec { + let res_to_ast_args = |file: &str| -> Vec { + let file = "../../".to_string() + file; vec![ vec!["-bs-v".to_string(), format!("{}", version)], ppx_flags, @@ -194,7 +195,7 @@ fn generate_ast( }; /* Create .ast */ - if let Some(res_to_ast) = helpers::canonicalize_string_path(file).map(|file| { + if let Some(res_to_ast) = Some(file).map(|file| { Command::new(helpers::get_bsc(&root_path)) .current_dir(helpers::canonicalize_string_path(&build_path_abs).unwrap()) .args(res_to_ast_args(file)) @@ -206,12 +207,14 @@ fn generate_ast( if res_to_ast.status.success() { Ok((ast_path, Some(stderr.to_string()))) } else { + println!("err: {}", stderr.to_string()); Err(stderr.to_string()) } } else { Ok((ast_path, None)) } } else { + println!("Parsing file {}...", file); return Err(format!( "Could not find canonicalize_string_path for file {} in package {}", file, package.name @@ -812,7 +815,6 @@ pub fn compile_file( is_interface: bool, ) -> Result, String> { let build_path_abs = helpers::get_build_path(root_path, &package.name); - let pkg_path_abs = helpers::get_package_path(root_path, &package.name); let bsc_flags = bsconfig::flatten_flags(&package.bsconfig.bsc_flags); let normal_deps = package @@ -933,8 +935,6 @@ pub fn compile_file( format!( "es6:{}:{}", Path::new(implementation_file_path) - .strip_prefix(pkg_path_abs) - .unwrap() .parent() .unwrap() .to_str() @@ -965,7 +965,7 @@ pub fn compile_file( // "-I".to_string(), // abs_node_modules_path.to_string() + "/rescript/ocaml", // ], - vec![helpers::canonicalize_string_path(&ast_path.to_owned()).unwrap()], + vec![ast_path.to_string()], ] .concat(); @@ -987,8 +987,6 @@ pub fn compile_file( .to_string(); let dir = std::path::Path::new(implementation_file_path) - .strip_prefix(helpers::get_package_path(root_path, &package.name)) - .unwrap() .parent() .unwrap(); diff --git a/src/clean.rs b/src/clean.rs index f614ce7..dd9e0d5 100644 --- a/src/clean.rs +++ b/src/clean.rs @@ -6,6 +6,7 @@ use crate::package_tree; use ahash::{AHashMap, AHashSet}; use rayon::prelude::*; use std::fs; +use std::path::PathBuf; use std::time::SystemTime; pub fn get_res_path_from_ast(ast_file: &str) -> Option { @@ -101,7 +102,14 @@ pub fn cleanup_previous_build(build_state: &mut BuildState) -> (usize, usize, AH .values() .filter_map(|module| match &module.source_type { SourceType::SourceFile(source_file) => { - Some(source_file.implementation.path.to_string()) + let package = build_state.packages.get(&module.package_name).unwrap(); + + Some( + PathBuf::from(&package.package_dir) + .join(source_file.implementation.path.to_owned()) + .to_string_lossy() + .to_string(), + ) } _ => None, }) @@ -112,9 +120,13 @@ pub fn cleanup_previous_build(build_state: &mut BuildState) -> (usize, usize, AH .modules .values() .filter_map(|module| { - build::get_interface(module) - .as_ref() - .map(|interface| interface.path.to_string()) + let package = build_state.packages.get(&module.package_name).unwrap(); + build::get_interface(module).as_ref().map(|interface| { + PathBuf::from(&package.package_dir) + .join(interface.path.to_owned()) + .to_string_lossy() + .to_string() + }) }) .collect::>(), ); @@ -181,12 +193,6 @@ pub fn cleanup_previous_build(build_state: &mut BuildState) -> (usize, usize, AH } } - let canonicalized_rescript_file_locations = rescript_file_locations - .iter() - .filter_map(|rescript_file_location| { - helpers::canonicalize_parent_string_path(rescript_file_location) - }) - .collect::>(); // delete the .mjs file which appear in our previous compile assets // but does not exists anymore // delete the compiler assets for which modules we can't find a rescript file @@ -194,38 +200,34 @@ pub fn cleanup_previous_build(build_state: &mut BuildState) -> (usize, usize, AH // delete the .mjs file for which we DO have a compiler asset, but don't have a // rescript file anymore (path is found in the .ast file) let diff = ast_rescript_file_locations - .difference(&canonicalized_rescript_file_locations) + .difference(&rescript_file_locations) .collect::>(); let diff_len = diff.len(); - diff.par_iter().for_each(|canonicalized_res_file_location| { + diff.par_iter().for_each(|res_file_location| { let (_module_name, package_name, package_namespace, _last_modified, _ast_file_path) = ast_modules - .get(&canonicalized_res_file_location.to_string()) + .get(&res_file_location.to_string()) .expect("Could not find module name for ast file"); - remove_asts( - canonicalized_res_file_location, - package_name, - &build_state.project_root, - ); + remove_asts(res_file_location, package_name, &build_state.project_root); remove_compile_assets( - canonicalized_res_file_location, + res_file_location, package_name, package_namespace, &build_state.project_root, ); - remove_mjs_file(&canonicalized_res_file_location) + remove_mjs_file(&res_file_location) }); ast_rescript_file_locations - .intersection(&canonicalized_rescript_file_locations) + .intersection(&rescript_file_locations) .into_iter() - .for_each(|canonicalized_res_file_location| { + .for_each(|res_file_location| { let (module_name, _package_name, package_namespace, ast_last_modified, ast_file_path) = ast_modules - .get(canonicalized_res_file_location) + .get(res_file_location) .expect("Could not find module name for ast file"); let module = build_state .modules @@ -393,22 +395,18 @@ pub fn cleanup_after_build(build_state: &BuildState) { match &module.source_type { SourceType::SourceFile(source_file) => { remove_compile_assets( - &helpers::canonicalize_parent_string_path( - &source_file.implementation.path, - ) - .unwrap(), + &source_file.implementation.path, &module.package_name, &package.namespace, &build_state.project_root, ); } SourceType::MlMap(_) => remove_compile_assets( - &helpers::canonicalize_string_path(&get_mlmap_path( + &get_mlmap_path( &build_state.project_root, &module.package_name, &package.namespace.to_suffix().unwrap(), - )) - .unwrap(), + ), &module.package_name, &package_tree::Namespace::NoNamespace, &build_state.project_root, diff --git a/src/helpers.rs b/src/helpers.rs index 525e786..a1cc8f8 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -43,6 +43,10 @@ impl LexicalAbsolute for Path { } } +pub fn get_relative_package_path(package_name: &str) -> String { + format!("node_modules/{}", package_name) +} + pub fn get_package_path(root: &str, package_name: &str) -> String { format!("{}/node_modules/{}", root, package_name) } @@ -197,24 +201,6 @@ pub fn canonicalize_string_path(path: &str) -> Option { .map(|path| path.to_str().expect("Could not canonicalize").to_string()); } -// sometimes we only want to canonicalize the parent path, if we potentially want to -// canonicalize file paths that might not exist anymore BUT the parent path does -pub fn canonicalize_parent_string_path(path: &str) -> Option { - return Path::new(path) - .parent() - .unwrap() - .canonicalize() - .ok() - .map(|dir| { - let filename = Path::new(path) - .file_name() - .expect("There should always be a filename"); - // add back file - let path = dir.join(filename); - return path.to_str().expect("Could not canonicalize").to_string(); - }); -} - pub fn get_bs_compiler_asset( source_file: &str, package_name: &str, @@ -226,15 +212,8 @@ pub fn get_bs_compiler_asset( "ast" | "iast" => &package_tree::Namespace::NoNamespace, _ => namespace, }; - let canonicalized_source_file = source_file; - let canonicalized_path = - canonicalize_string_path(&get_package_path(root_path, &package_name)).unwrap(); - let dir = std::path::Path::new(&canonicalized_source_file) - .strip_prefix(canonicalized_path) - .unwrap() - .parent() - .unwrap(); + let dir = std::path::Path::new(&source_file).parent().unwrap(); std::path::Path::new(&get_bs_build_path(root_path, &package_name)) .join(dir) diff --git a/src/package_tree.rs b/src/package_tree.rs index 31a195e..3fdb9e9 100644 --- a/src/package_tree.rs +++ b/src/package_tree.rs @@ -1,7 +1,5 @@ use crate::bsconfig; -use crate::bsconfig::*; use crate::helpers; -use crate::helpers::{is_source_file, LexicalAbsolute}; use ahash::{AHashMap, AHashSet}; use convert_case::{Case, Casing}; use rayon::prelude::*; @@ -39,11 +37,12 @@ impl Namespace { pub struct Package { pub name: String, pub bsconfig: bsconfig::T, - pub source_folders: AHashSet<(String, bsconfig::PackageSource)>, + pub source_folders: AHashSet, // these are the relative file paths (relative to the package root) pub source_files: Option>, pub namespace: Namespace, pub modules: Option>, + // canonicalized dir of the package pub package_dir: String, pub dirs: Option>, pub is_pinned_dep: bool, @@ -70,25 +69,23 @@ fn matches_filter(filter: &Option, path: &str) -> bool { pub fn read_folders( filter: &Option, + package_dir: &Path, path: &Path, recurse: bool, ) -> Result, Box> { let mut map: AHashMap = AHashMap::new(); let path_buf = PathBuf::from(path); - - let path_lex_abs = &path_buf.to_lexical_absolute().unwrap(); - - let meta = fs::metadata(path_lex_abs); + let meta = fs::metadata(package_dir.join(&path)); let path_with_meta = meta.map(|meta| { ( - path_lex_abs.to_str().unwrap().to_string(), + path.to_owned(), SourceFileMeta { modified: meta.modified().unwrap(), }, ) }); - for entry in fs::read_dir(&path_buf)? { + for entry in fs::read_dir(package_dir.join(&path_buf))? { let entry_path_buf = entry.map(|entry| entry.path())?; let metadata = fs::metadata(&entry_path_buf)?; let name = entry_path_buf @@ -101,17 +98,19 @@ pub fn read_folders( let path_ext = entry_path_buf.extension().and_then(|x| x.to_str()); let new_path = path_buf.join(&name); if metadata.file_type().is_dir() && recurse { - match read_folders(&filter, &new_path, recurse) { + match read_folders(&filter, package_dir, &new_path, recurse) { Ok(s) => map.extend(s), Err(e) => println!("Error reading directory: {}", e), } } match path_ext { - Some(extension) if is_source_file(extension) => match path_with_meta { + Some(extension) if helpers::is_source_file(extension) => match path_with_meta { Ok((ref path, _)) if matches_filter(filter, &name) => { + let mut path = path.to_owned(); + path.push(&name); map.insert( - path.to_owned() + "/" + &name, + path.to_string_lossy().to_string(), SourceFileMeta { modified: metadata.modified().unwrap(), }, @@ -133,40 +132,36 @@ pub fn read_folders( /// because of the recursiveness. So you get a flat list of files back, retaining the type_ and /// wether it needs to recurse into all structures fn get_source_dirs( - project_root: &str, - source: Source, -) -> AHashSet<(String, bsconfig::PackageSource)> { - let mut source_folders: AHashSet<(String, bsconfig::PackageSource)> = AHashSet::new(); - - let (package_root, subdirs, full_recursive) = match source.to_owned() { - Source::Shorthand(dir) - | Source::Qualified(PackageSource { - dir, subdirs: None, .. - }) => (dir, None, false), - Source::Qualified(PackageSource { - dir, - subdirs: Some(Subdirs::Recurse(recurse)), + source: bsconfig::Source, + sub_path: Option, +) -> AHashSet { + let mut source_folders: AHashSet = AHashSet::new(); + + let (subdirs, full_recursive) = match source.to_owned() { + bsconfig::Source::Shorthand(_) + | bsconfig::Source::Qualified(bsconfig::PackageSource { subdirs: None, .. }) => { + (None, false) + } + bsconfig::Source::Qualified(bsconfig::PackageSource { + subdirs: Some(bsconfig::Subdirs::Recurse(recurse)), .. - }) => (dir, None, recurse), - Source::Qualified(PackageSource { - dir, - subdirs: Some(Subdirs::Qualified(subdirs)), + }) => (None, recurse), + bsconfig::Source::Qualified(bsconfig::PackageSource { + subdirs: Some(bsconfig::Subdirs::Qualified(subdirs)), .. - }) => (dir, Some(subdirs), false), + }) => (Some(subdirs), false), }; - let full_path = project_root.to_string() + "/" + &package_root; - source_folders.insert(( - full_path.to_owned(), - bsconfig::to_qualified_without_children(&source), - )); + let source_folder = bsconfig::to_qualified_without_children(&source, sub_path.to_owned()); + source_folders.insert(source_folder.to_owned()); if !full_recursive { + let sub_path = Path::new(&source_folder.dir).to_path_buf(); subdirs .unwrap_or(vec![]) .par_iter() - .map(|subdir| get_source_dirs(&full_path, subdir.to_owned())) - .collect::>>() + .map(|subdir| get_source_dirs(subdir.to_owned(), Some(sub_path.to_owned()))) + .collect::>>() .into_iter() .for_each(|subdir| source_folders.extend(subdir)) } @@ -174,15 +169,18 @@ fn get_source_dirs( source_folders } -fn get_package_dir(package_name: &str, is_root: bool, project_root: &str) -> String { +fn get_package_dir(package_name: &str, is_root: bool) -> String { if is_root { - project_root.to_owned() + "".to_string() } else { - helpers::get_package_path(project_root, package_name) + helpers::get_relative_package_path(&package_name) } } fn read_bsconfig(package_dir: &str) -> bsconfig::T { + if package_dir == "" { + return bsconfig::read("bsconfig.json".to_string()); + } bsconfig::read(package_dir.to_string() + "/bsconfig.json") } @@ -193,10 +191,8 @@ fn build_package<'a>( map: &'a mut AHashMap, bsconfig: bsconfig::T, package_dir: &str, - // is_root: bool, project_root: &str, is_pinned_dep: bool, - // package_name: &str, ) -> &'a mut AHashMap { // let (package_dir, bsconfig) = read_bsconfig(package_name, project_root, is_root); let copied_bsconfig = bsconfig.to_owned(); @@ -207,14 +203,13 @@ fn build_package<'a>( * one as that is an expensive operation IO wise and we don't want to duplicate that.*/ map.insert(copied_bsconfig.name.to_owned(), { let source_folders = match bsconfig.sources.to_owned() { - bsconfig::OneOrMore::Single(source) => get_source_dirs(&package_dir, source), + bsconfig::OneOrMore::Single(source) => get_source_dirs(source, None), bsconfig::OneOrMore::Multiple(sources) => { - let mut source_folders: AHashSet<(String, bsconfig::PackageSource)> = - AHashSet::new(); + let mut source_folders: AHashSet = AHashSet::new(); sources .iter() - .map(|source| get_source_dirs(&package_dir, source.to_owned())) - .collect::>>() + .map(|source| get_source_dirs(source.to_owned(), None)) + .collect::>>() .into_iter() .for_each(|source| source_folders.extend(source)); source_folders @@ -276,7 +271,11 @@ fn build_package<'a>( .unwrap_or(vec![]) .iter() .filter_map(|package_name| { - let package_dir = get_package_dir(package_name, false, project_root); + let package_dir = PathBuf::from(get_package_dir(package_name, false)) + .canonicalize() + .expect("Could not canonicalize package dir") + .to_string_lossy() + .to_string(); if !map.contains_key(package_name) { Some(package_dir) } else { @@ -313,30 +312,33 @@ fn build_package<'a>( /// NPM package. The file reader allows for this, just warns when this happens. /// TODO -> Check wether we actually need the `fs::Metadata` pub fn get_source_files( + package_dir: &Path, filter: &Option, - dir: &String, - source: &PackageSource, + source: &bsconfig::PackageSource, ) -> AHashMap { let mut map: AHashMap = AHashMap::new(); let (recurse, type_) = match source { - PackageSource { - subdirs: Some(Subdirs::Recurse(subdirs)), + bsconfig::PackageSource { + subdirs: Some(bsconfig::Subdirs::Recurse(subdirs)), type_, .. } => (subdirs.to_owned(), type_), - PackageSource { type_, .. } => (false, type_), + bsconfig::PackageSource { type_, .. } => (false, type_), }; - let path_dir = Path::new(dir); + let path_dir = Path::new(&source.dir); // don't include dev sources for now if type_ != &Some("dev".to_string()) { - match read_folders(&filter, path_dir, recurse) { + match read_folders(&filter, package_dir, path_dir, recurse) { Ok(files) => map.extend(files), Err(_e) if type_ == &Some("dev".to_string()) => { - println!("Could not read folder: {dir}... Probably ok as type is dev") + println!( + "Could not read folder: {}... Probably ok as type is dev", + path_dir.to_string_lossy() + ) } - Err(_e) => println!("Could not read folder: {dir}..."), + Err(_e) => println!("Could not read folder: {}...", path_dir.to_string_lossy()), } } @@ -362,7 +364,7 @@ fn extend_with_children( value .source_folders .par_iter() - .map(|(dir, source)| get_source_files(&filter, dir, source)) + .map(|source| get_source_files(Path::new(&value.package_dir), &filter, source)) .collect::>>() .into_iter() .for_each(|source| map.extend(source)); @@ -386,11 +388,7 @@ fn extend_with_children( value.modules = Some(modules); let mut dirs = AHashSet::new(); map.keys().for_each(|path| { - let dir = std::path::Path::new(&path) - .strip_prefix(&value.package_dir) - .unwrap() - .parent() - .unwrap(); + let dir = std::path::Path::new(&path).parent().unwrap(); dirs.insert(dir.to_owned()); }); value.dirs = Some(dirs); @@ -410,7 +408,7 @@ pub fn make(filter: &Option, root_folder: &str) -> AHashMap = AHashMap::new(); - let package_dir = get_package_dir("", true, root_folder); + let package_dir = get_package_dir("", true); let bsconfig = read_bsconfig(&package_dir); build_package(&mut map, bsconfig, &package_dir, root_folder, true); /* Once we have the deduplicated packages, we can add the source files for each - to minimize