summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/tools/registry/diagnostics.rs22
-rw-r--r--cli/tools/registry/mod.rs68
2 files changed, 89 insertions, 1 deletions
diff --git a/cli/tools/registry/diagnostics.rs b/cli/tools/registry/diagnostics.rs
index 34f08b666..54b281194 100644
--- a/cli/tools/registry/diagnostics.rs
+++ b/cli/tools/registry/diagnostics.rs
@@ -119,6 +119,10 @@ pub enum PublishDiagnostic {
range: SourceRange,
},
SyntaxError(ParseDiagnostic),
+ MissingLicense {
+ /// This only exists because diagnostics require a location.
+ expected_path: PathBuf,
+ },
}
impl PublishDiagnostic {
@@ -168,6 +172,8 @@ impl Diagnostic for PublishDiagnostic {
MissingConstraint { .. } => DiagnosticLevel::Error,
BannedTripleSlashDirectives { .. } => DiagnosticLevel::Error,
SyntaxError { .. } => DiagnosticLevel::Error,
+ // todo(#24676): make this an error in Deno 1.46
+ MissingLicense { .. } => DiagnosticLevel::Warning,
}
}
@@ -187,6 +193,7 @@ impl Diagnostic for PublishDiagnostic {
Cow::Borrowed("banned-triple-slash-directives")
}
SyntaxError { .. } => Cow::Borrowed("syntax-error"),
+ MissingLicense { .. } => Cow::Borrowed("missing-license"),
}
}
@@ -208,6 +215,7 @@ impl Diagnostic for PublishDiagnostic {
MissingConstraint { specifier, .. } => Cow::Owned(format!("specifier '{}' is missing a version constraint", specifier)),
BannedTripleSlashDirectives { .. } => Cow::Borrowed("triple slash directives that modify globals are not allowed"),
SyntaxError(diagnostic) => diagnostic.message(),
+ MissingLicense { .. } => Cow::Borrowed("missing license file"),
}
}
@@ -275,6 +283,9 @@ impl Diagnostic for PublishDiagnostic {
text_info: Cow::Borrowed(text_info),
},
SyntaxError(diagnostic) => diagnostic.location(),
+ MissingLicense { expected_path } => DiagnosticLocation::Path {
+ path: expected_path.clone(),
+ },
}
}
@@ -355,6 +366,7 @@ impl Diagnostic for PublishDiagnostic {
}],
}),
SyntaxError(diagnostic) => diagnostic.snippet(),
+ MissingLicense { .. } => None,
}
}
@@ -388,6 +400,9 @@ impl Diagnostic for PublishDiagnostic {
Cow::Borrowed("remove the triple slash directive"),
),
SyntaxError(diagnostic) => diagnostic.hint(),
+ MissingLicense { .. } => Some(
+ Cow::Borrowed("add a LICENSE file to the package and ensure it is not ignored from being published"),
+ ),
}
}
@@ -424,7 +439,8 @@ impl Diagnostic for PublishDiagnostic {
| UnsupportedJsxTsx { .. }
| ExcludedModule { .. }
| MissingConstraint { .. }
- | BannedTripleSlashDirectives { .. } => None,
+ | BannedTripleSlashDirectives { .. }
+ | MissingLicense { .. } => None,
}
}
@@ -474,6 +490,7 @@ impl Diagnostic for PublishDiagnostic {
Cow::Borrowed("or set their 'lib' compiler option appropriately"),
]),
SyntaxError(diagnostic) => diagnostic.info(),
+ MissingLicense { .. } => Cow::Borrowed(&[]),
}
}
@@ -507,6 +524,9 @@ impl Diagnostic for PublishDiagnostic {
"https://jsr.io/go/banned-triple-slash-directives",
)),
SyntaxError(diagnostic) => diagnostic.docs_url(),
+ MissingLicense { .. } => {
+ Some(Cow::Borrowed("https://jsr.io/go/missing-license"))
+ }
}
}
}
diff --git a/cli/tools/registry/mod.rs b/cli/tools/registry/mod.rs
index 2e781ccee..1c4e1bea7 100644
--- a/cli/tools/registry/mod.rs
+++ b/cli/tools/registry/mod.rs
@@ -462,6 +462,13 @@ impl PublishPreparer {
&publish_paths,
&diagnostics_collector,
);
+
+ if !has_license_file(publish_paths.iter().map(|p| &p.specifier)) {
+ diagnostics_collector.push(PublishDiagnostic::MissingLicense {
+ expected_path: root_dir.join("LICENSE"),
+ });
+ }
+
tar::create_gzipped_tarball(
&publish_paths,
LazyGraphSourceParser::new(&source_cache, &graph),
@@ -1187,6 +1194,36 @@ async fn check_if_git_repo_dirty(cwd: &Path) -> Option<String> {
}
}
+fn has_license_file<'a>(
+ mut specifiers: impl Iterator<Item = &'a ModuleSpecifier>,
+) -> bool {
+ let allowed_license_files = {
+ let files = HashSet::from([
+ "license",
+ "license.md",
+ "license.txt",
+ "licence",
+ "licence.md",
+ "licence.txt",
+ ]);
+ if cfg!(debug_assertions) {
+ for file in &files {
+ assert_eq!(*file, file.to_lowercase());
+ }
+ }
+ files
+ };
+ specifiers.any(|specifier| {
+ specifier
+ .path()
+ .rsplit_once('/')
+ .map(|(_, file)| {
+ allowed_license_files.contains(file.to_lowercase().as_str())
+ })
+ .unwrap_or(false)
+ })
+}
+
#[allow(clippy::print_stderr)]
fn ring_bell() {
// ASCII code for the bell character.
@@ -1195,6 +1232,10 @@ fn ring_bell() {
#[cfg(test)]
mod tests {
+ use deno_ast::ModuleSpecifier;
+
+ use crate::tools::registry::has_license_file;
+
use super::tar::PublishableTarball;
use super::tar::PublishableTarballFile;
use super::verify_version_manifest;
@@ -1296,4 +1337,31 @@ mod tests {
assert!(verify_version_manifest(meta_bytes, &package).is_err());
}
+
+ #[test]
+ fn test_has_license_files() {
+ fn has_license_file_str(expected: &[&str]) -> bool {
+ let specifiers = expected
+ .iter()
+ .map(|s| ModuleSpecifier::parse(s).unwrap())
+ .collect::<Vec<_>>();
+ has_license_file(specifiers.iter())
+ }
+
+ assert!(has_license_file_str(&["file:///LICENSE"]));
+ assert!(has_license_file_str(&["file:///license"]));
+ assert!(has_license_file_str(&["file:///LICENSE.txt"]));
+ assert!(has_license_file_str(&["file:///LICENSE.md"]));
+ assert!(has_license_file_str(&["file:///LICENCE"]));
+ assert!(has_license_file_str(&["file:///LICENCE.txt"]));
+ assert!(has_license_file_str(&["file:///LICENCE.md"]));
+ assert!(has_license_file_str(&[
+ "file:///other",
+ "file:///test/LICENCE.md"
+ ]),);
+ assert!(!has_license_file_str(&[
+ "file:///other",
+ "file:///test/tLICENSE"
+ ]),);
+ }
}