diff options
Diffstat (limited to 'cli/tools/registry/paths.rs')
-rw-r--r-- | cli/tools/registry/paths.rs | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/cli/tools/registry/paths.rs b/cli/tools/registry/paths.rs index 86c04a7cb..12282b77a 100644 --- a/cli/tools/registry/paths.rs +++ b/cli/tools/registry/paths.rs @@ -2,8 +2,22 @@ // Validation logic in this file is shared with registry/api/src/ids.rs +use std::collections::HashSet; +use std::path::Path; +use std::path::PathBuf; + +use deno_ast::MediaType; +use deno_ast::ModuleSpecifier; +use deno_config::glob::FilePatterns; +use deno_core::error::AnyError; use thiserror::Error; +use crate::args::CliOptions; +use crate::util::fs::FileCollector; + +use super::diagnostics::PublishDiagnostic; +use super::diagnostics::PublishDiagnosticsCollector; + /// A package path, like '/foo' or '/foo/bar'. The path is prefixed with a slash /// and does not end with a slash. /// @@ -196,3 +210,124 @@ pub enum PackagePathValidationError { #[error("package path must not contain invalid characters (found '{}')", .0.escape_debug())] InvalidOtherChar(char), } + +pub struct CollectedPublishPath { + pub specifier: ModuleSpecifier, + pub path: PathBuf, + pub relative_path: String, +} + +pub fn collect_publish_paths( + root_dir: &Path, + cli_options: &CliOptions, + diagnostics_collector: &PublishDiagnosticsCollector, + file_patterns: FilePatterns, +) -> Result<Vec<CollectedPublishPath>, AnyError> { + let publish_paths = + collect_paths(cli_options, diagnostics_collector, file_patterns)?; + let mut paths = HashSet::with_capacity(publish_paths.len()); + let mut result = Vec::with_capacity(publish_paths.len()); + for path in publish_paths { + let Ok(specifier) = ModuleSpecifier::from_file_path(&path) else { + diagnostics_collector + .to_owned() + .push(PublishDiagnostic::InvalidPath { + path: path.to_path_buf(), + message: "unable to convert path to url".to_string(), + }); + continue; + }; + + let Ok(relative_path) = path.strip_prefix(root_dir) else { + diagnostics_collector + .to_owned() + .push(PublishDiagnostic::InvalidPath { + path: path.to_path_buf(), + message: "path is not in publish directory".to_string(), + }); + continue; + }; + + let relative_path = + relative_path + .components() + .fold("".to_string(), |mut path, component| { + path.push('/'); + match component { + std::path::Component::Normal(normal) => { + path.push_str(&normal.to_string_lossy()) + } + std::path::Component::CurDir => path.push('.'), + std::path::Component::ParentDir => path.push_str(".."), + _ => unreachable!(), + } + path + }); + + match PackagePath::new(relative_path.clone()) { + Ok(package_path) => { + if !paths.insert(package_path) { + diagnostics_collector.to_owned().push( + PublishDiagnostic::DuplicatePath { + path: path.to_path_buf(), + }, + ); + } + } + Err(err) => { + diagnostics_collector + .to_owned() + .push(PublishDiagnostic::InvalidPath { + path: path.to_path_buf(), + message: err.to_string(), + }); + } + } + + let media_type = MediaType::from_specifier(&specifier); + if matches!(media_type, MediaType::Jsx | MediaType::Tsx) { + diagnostics_collector.push(PublishDiagnostic::UnsupportedJsxTsx { + specifier: specifier.clone(), + }); + } + + result.push(CollectedPublishPath { + specifier, + path, + relative_path, + }); + } + + Ok(result) +} + +fn collect_paths( + cli_options: &CliOptions, + diagnostics_collector: &PublishDiagnosticsCollector, + file_patterns: FilePatterns, +) -> Result<Vec<PathBuf>, AnyError> { + FileCollector::new(|e| { + if !e.file_type.is_file() { + if let Ok(specifier) = ModuleSpecifier::from_file_path(e.path) { + diagnostics_collector.push(PublishDiagnostic::UnsupportedFileType { + specifier, + kind: if e.file_type.is_symlink() { + "symlink".to_owned() + } else { + format!("{:?}", e.file_type) + }, + }); + } + return false; + } + e.path + .file_name() + .map(|s| s != ".DS_Store" && s != ".gitignore") + .unwrap_or(true) + }) + .ignore_git_folder() + .ignore_node_modules() + .set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned)) + .use_gitignore() + .collect_file_patterns(file_patterns) +} |