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:
parent
5f5f662a68
commit
84b7504d0f
7 changed files with 108 additions and 32 deletions
|
@ -4,6 +4,7 @@ use std::collections::HashMap;
|
|||
use std::collections::HashSet;
|
||||
use std::io::IsTerminal;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Stdio;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
@ -13,6 +14,7 @@ use base64::Engine;
|
|||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::workspace::JsrPackageConfig;
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_config::workspace::Workspace;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
|
@ -448,7 +450,7 @@ impl PublishPreparer {
|
|||
move || {
|
||||
let root_specifier =
|
||||
ModuleSpecifier::from_directory_path(&root_dir).unwrap();
|
||||
let publish_paths =
|
||||
let mut publish_paths =
|
||||
paths::collect_publish_paths(paths::CollectPublishPathsOptions {
|
||||
root_dir: &root_dir,
|
||||
cli_options: &cli_options,
|
||||
|
@ -464,13 +466,28 @@ impl PublishPreparer {
|
|||
);
|
||||
|
||||
if !has_license_file(publish_paths.iter().map(|p| &p.specifier)) {
|
||||
if let Some(license_path) =
|
||||
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(
|
||||
&publish_paths,
|
||||
publish_paths,
|
||||
LazyGraphSourceParser::new(&source_cache, &graph),
|
||||
&diagnostics_collector,
|
||||
&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>(
|
||||
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
|
||||
};
|
||||
let supported_license_files = SUPPORTED_LICENSE_FILE_NAMES
|
||||
.iter()
|
||||
.map(|s| s.to_lowercase())
|
||||
.collect::<HashSet<_>>();
|
||||
specifiers.any(|specifier| {
|
||||
specifier
|
||||
.path()
|
||||
.rsplit_once('/')
|
||||
.map(|(_, file)| {
|
||||
allowed_license_files.contains(file.to_lowercase().as_str())
|
||||
supported_license_files.contains(file.to_lowercase().as_str())
|
||||
})
|
||||
.unwrap_or(false)
|
||||
})
|
||||
|
|
|
@ -214,7 +214,10 @@ pub enum PackagePathValidationError {
|
|||
pub struct CollectedPublishPath {
|
||||
pub specifier: ModuleSpecifier,
|
||||
pub path: PathBuf,
|
||||
/// Relative path to use in the tarball.
|
||||
pub relative_path: String,
|
||||
/// Specify the contents for any injected paths.
|
||||
pub maybe_content: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
pub struct CollectPublishPathsOptions<'a> {
|
||||
|
@ -307,6 +310,7 @@ pub fn collect_publish_paths(
|
|||
specifier,
|
||||
path,
|
||||
relative_path,
|
||||
maybe_content: None,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ pub struct PublishableTarball {
|
|||
}
|
||||
|
||||
pub fn create_gzipped_tarball(
|
||||
publish_paths: &[CollectedPublishPath],
|
||||
publish_paths: Vec<CollectedPublishPath>,
|
||||
source_parser: LazyGraphSourceParser,
|
||||
diagnostics_collector: &PublishDiagnosticsCollector,
|
||||
unfurler: &SpecifierUnfurler,
|
||||
|
@ -45,15 +45,17 @@ pub fn create_gzipped_tarball(
|
|||
for path in publish_paths {
|
||||
let path_str = &path.relative_path;
|
||||
let specifier = &path.specifier;
|
||||
let path = &path.path;
|
||||
|
||||
let content = resolve_content_maybe_unfurling(
|
||||
path,
|
||||
let content = match path.maybe_content {
|
||||
Some(content) => content.clone(),
|
||||
None => resolve_content_maybe_unfurling(
|
||||
&path.path,
|
||||
specifier,
|
||||
unfurler,
|
||||
source_parser,
|
||||
diagnostics_collector,
|
||||
)?;
|
||||
)?,
|
||||
};
|
||||
|
||||
files.push(PublishableTarballFile {
|
||||
path_str: path_str.clone(),
|
||||
|
@ -65,7 +67,7 @@ pub fn create_gzipped_tarball(
|
|||
tar
|
||||
.add_file(format!(".{}", path_str), &content)
|
||||
.with_context(|| {
|
||||
format!("Unable to add file to tarball '{}'", path.display())
|
||||
format!("Unable to add file to tarball '{}'", path.path.display())
|
||||
})?;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,15 @@
|
|||
"args": "publish --token 'sadfasdf'",
|
||||
"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": {
|
||||
"cwd": "./bar",
|
||||
"args": "publish --token 'sadfasdf'",
|
||||
|
|
9
tests/specs/publish/workspace/foo_dry_run.out
Normal file
9
tests/specs/publish/workspace/foo_dry_run.out
Normal 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
|
17
tests/specs/publish/workspace/workspace_dry_run.out
Normal file
17
tests/specs/publish/workspace/workspace_dry_run.out
Normal 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
|
Loading…
Reference in a new issue