1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

fix(workspaces/publish): include the license file from the workspace root if not in pkg (#24714)

This commit is contained in:
David Sherret 2024-07-24 21:43:30 -04:00 committed by GitHub
parent 5f5f662a68
commit 84b7504d0f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 108 additions and 32 deletions

View file

@ -4,6 +4,7 @@ use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use std::io::IsTerminal; use std::io::IsTerminal;
use std::path::Path; use std::path::Path;
use std::path::PathBuf;
use std::process::Stdio; use std::process::Stdio;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -13,6 +14,7 @@ use base64::Engine;
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;
use deno_config::workspace::JsrPackageConfig; use deno_config::workspace::JsrPackageConfig;
use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::PackageJsonDepResolution;
use deno_config::workspace::Workspace;
use deno_core::anyhow::bail; use deno_core::anyhow::bail;
use deno_core::anyhow::Context; use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
@ -448,7 +450,7 @@ impl PublishPreparer {
move || { move || {
let root_specifier = let root_specifier =
ModuleSpecifier::from_directory_path(&root_dir).unwrap(); ModuleSpecifier::from_directory_path(&root_dir).unwrap();
let publish_paths = let mut publish_paths =
paths::collect_publish_paths(paths::CollectPublishPathsOptions { paths::collect_publish_paths(paths::CollectPublishPathsOptions {
root_dir: &root_dir, root_dir: &root_dir,
cli_options: &cli_options, cli_options: &cli_options,
@ -464,13 +466,28 @@ impl PublishPreparer {
); );
if !has_license_file(publish_paths.iter().map(|p| &p.specifier)) { if !has_license_file(publish_paths.iter().map(|p| &p.specifier)) {
diagnostics_collector.push(PublishDiagnostic::MissingLicense { if let Some(license_path) =
expected_path: root_dir.join("LICENSE"), resolve_license_file(&root_dir, cli_options.workspace())
}); {
// force including the license file from the package or workspace root
publish_paths.push(CollectedPublishPath {
specifier: ModuleSpecifier::from_file_path(&license_path)
.unwrap(),
relative_path: "LICENSE".to_string(),
maybe_content: Some(std::fs::read(&license_path).with_context(
|| format!("failed reading '{}'.", license_path.display()),
)?),
path: license_path,
});
} else {
diagnostics_collector.push(PublishDiagnostic::MissingLicense {
expected_path: root_dir.join("LICENSE"),
});
}
} }
tar::create_gzipped_tarball( tar::create_gzipped_tarball(
&publish_paths, publish_paths,
LazyGraphSourceParser::new(&source_cache, &graph), LazyGraphSourceParser::new(&source_cache, &graph),
&diagnostics_collector, &diagnostics_collector,
&unfurler, &unfurler,
@ -1194,31 +1211,49 @@ async fn check_if_git_repo_dirty(cwd: &Path) -> Option<String> {
} }
} }
static SUPPORTED_LICENSE_FILE_NAMES: [&str; 6] = [
"LICENSE",
"LICENSE.md",
"LICENSE.txt",
"LICENCE",
"LICENCE.md",
"LICENCE.txt",
];
fn resolve_license_file(
pkg_root_dir: &Path,
workspace: &Workspace,
) -> Option<PathBuf> {
let workspace_root_dir = workspace.root_dir_path();
let mut dirs = Vec::with_capacity(2);
dirs.push(pkg_root_dir);
if workspace_root_dir != pkg_root_dir {
dirs.push(&workspace_root_dir);
}
for dir in dirs {
for file_name in &SUPPORTED_LICENSE_FILE_NAMES {
let file_path = dir.join(file_name);
if file_path.exists() {
return Some(file_path);
}
}
}
None
}
fn has_license_file<'a>( fn has_license_file<'a>(
mut specifiers: impl Iterator<Item = &'a ModuleSpecifier>, mut specifiers: impl Iterator<Item = &'a ModuleSpecifier>,
) -> bool { ) -> bool {
let allowed_license_files = { let supported_license_files = SUPPORTED_LICENSE_FILE_NAMES
let files = HashSet::from([ .iter()
"license", .map(|s| s.to_lowercase())
"license.md", .collect::<HashSet<_>>();
"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| { specifiers.any(|specifier| {
specifier specifier
.path() .path()
.rsplit_once('/') .rsplit_once('/')
.map(|(_, file)| { .map(|(_, file)| {
allowed_license_files.contains(file.to_lowercase().as_str()) supported_license_files.contains(file.to_lowercase().as_str())
}) })
.unwrap_or(false) .unwrap_or(false)
}) })

View file

@ -214,7 +214,10 @@ pub enum PackagePathValidationError {
pub struct CollectedPublishPath { pub struct CollectedPublishPath {
pub specifier: ModuleSpecifier, pub specifier: ModuleSpecifier,
pub path: PathBuf, pub path: PathBuf,
/// Relative path to use in the tarball.
pub relative_path: String, pub relative_path: String,
/// Specify the contents for any injected paths.
pub maybe_content: Option<Vec<u8>>,
} }
pub struct CollectPublishPathsOptions<'a> { pub struct CollectPublishPathsOptions<'a> {
@ -307,6 +310,7 @@ pub fn collect_publish_paths(
specifier, specifier,
path, path,
relative_path, relative_path,
maybe_content: None,
}); });
} }

View file

@ -34,7 +34,7 @@ pub struct PublishableTarball {
} }
pub fn create_gzipped_tarball( pub fn create_gzipped_tarball(
publish_paths: &[CollectedPublishPath], publish_paths: Vec<CollectedPublishPath>,
source_parser: LazyGraphSourceParser, source_parser: LazyGraphSourceParser,
diagnostics_collector: &PublishDiagnosticsCollector, diagnostics_collector: &PublishDiagnosticsCollector,
unfurler: &SpecifierUnfurler, unfurler: &SpecifierUnfurler,
@ -45,15 +45,17 @@ pub fn create_gzipped_tarball(
for path in publish_paths { for path in publish_paths {
let path_str = &path.relative_path; let path_str = &path.relative_path;
let specifier = &path.specifier; let specifier = &path.specifier;
let path = &path.path;
let content = resolve_content_maybe_unfurling( let content = match path.maybe_content {
path, Some(content) => content.clone(),
specifier, None => resolve_content_maybe_unfurling(
unfurler, &path.path,
source_parser, specifier,
diagnostics_collector, unfurler,
)?; source_parser,
diagnostics_collector,
)?,
};
files.push(PublishableTarballFile { files.push(PublishableTarballFile {
path_str: path_str.clone(), path_str: path_str.clone(),
@ -65,7 +67,7 @@ pub fn create_gzipped_tarball(
tar tar
.add_file(format!(".{}", path_str), &content) .add_file(format!(".{}", path_str), &content)
.with_context(|| { .with_context(|| {
format!("Unable to add file to tarball '{}'", path.display()) format!("Unable to add file to tarball '{}'", path.path.display())
})?; })?;
} }

View file

@ -4,6 +4,15 @@
"args": "publish --token 'sadfasdf'", "args": "publish --token 'sadfasdf'",
"output": "workspace.out" "output": "workspace.out"
}, },
"workspace_dry_run": {
"args": "publish --token 'sadfasdf' --dry-run",
"output": "workspace_dry_run.out"
},
"individual_dry_run": {
"cwd": "./foo",
"args": "publish --token 'sadfasdf' --dry-run",
"output": "foo_dry_run.out"
},
"individual": { "individual": {
"cwd": "./bar", "cwd": "./bar",
"args": "publish --token 'sadfasdf'", "args": "publish --token 'sadfasdf'",

View file

@ -0,0 +1,9 @@
Check file:///[WILDLINE]/foo/mod.ts
Checking for slow types in the public API...
Check file:///[WILDLINE]/foo/mod.ts
Simulating publish of @foo/foo@1.0.0 with files:
[# notice how this line is including the LICENSE from the root directory]
file:///[WILDLINE]/workspace/LICENSE (0B)
file:///[WILDLINE]/workspace/foo/deno.json (135B)
file:///[WILDLINE]/workspace/foo/mod.ts (118B)
Warning Aborting due to --dry-run

View file

@ -0,0 +1,17 @@
Publishing a workspace...
Check file:///[WILDLINE]/workspace/bar/mod.ts
Check file:///[WILDLINE]/workspace/foo/mod.ts
Checking for slow types in the public API...
Check file:///[WILDLINE]/workspace/bar/mod.ts
Check file:///[WILDLINE]/workspace/foo/mod.ts
[UNORDERED_START]
Simulating publish of @foo/foo@1.0.0 with files:
file:///[WILDLINE]/workspace/LICENSE (0B)
file:///[WILDLINE]/workspace/foo/deno.json (135B)
file:///[WILDLINE]/workspace/foo/mod.ts (118B)
Simulating publish of @foo/bar@1.0.0 with files:
file:///[WILDLINE]/workspace/bar/LICENSE (0B)
file:///[WILDLINE]/workspace/bar/deno.json (87B)
file:///[WILDLINE]/workspace/bar/mod.ts (70B)
[UNORDERED_END]
Warning Aborting due to --dry-run