summaryrefslogtreecommitdiff
path: root/cli/tools/registry/paths.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/registry/paths.rs')
-rw-r--r--cli/tools/registry/paths.rs135
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)
+}