mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
feat(publish): respect .gitignore during deno publish
(#22514)
Files from `.gitignore`, global git config, `.git/info/exclude` and `deno.json`'s `exclude` are ignored.
This commit is contained in:
parent
ae703041b1
commit
f49abcc1ac
4 changed files with 156 additions and 19 deletions
51
Cargo.lock
generated
51
Cargo.lock
generated
|
@ -499,6 +499,16 @@ dependencies = [
|
||||||
"alloc-stdlib",
|
"alloc-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.14.0"
|
version = "3.14.0"
|
||||||
|
@ -1060,6 +1070,7 @@ dependencies = [
|
||||||
"glibc_version",
|
"glibc_version",
|
||||||
"glob",
|
"glob",
|
||||||
"hex",
|
"hex",
|
||||||
|
"ignore",
|
||||||
"import_map",
|
"import_map",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"jsonc-parser",
|
"jsonc-parser",
|
||||||
|
@ -2847,6 +2858,19 @@ version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "globset"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"bstr",
|
||||||
|
"log",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glow"
|
name = "glow"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
@ -3314,6 +3338,23 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ignore"
|
||||||
|
version = "0.4.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
|
||||||
|
dependencies = [
|
||||||
|
"globset",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"memchr",
|
||||||
|
"regex",
|
||||||
|
"same-file",
|
||||||
|
"thread_local",
|
||||||
|
"walkdir",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.24.7"
|
version = "0.24.7"
|
||||||
|
@ -6482,6 +6523,16 @@ dependencies = [
|
||||||
"syn 2.0.48",
|
"syn 2.0.48",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
|
|
|
@ -106,6 +106,7 @@ flate2.workspace = true
|
||||||
fs3.workspace = true
|
fs3.workspace = true
|
||||||
glob = "0.3.1"
|
glob = "0.3.1"
|
||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
|
ignore = "0.4"
|
||||||
import_map = { version = "=0.18.3", features = ["ext"] }
|
import_map = { version = "=0.18.3", features = ["ext"] }
|
||||||
indexmap.workspace = true
|
indexmap.workspace = true
|
||||||
jsonc-parser = { version = "=0.23.0", features = ["serde"] }
|
jsonc-parser = { version = "=0.23.0", features = ["serde"] }
|
||||||
|
|
|
@ -3,12 +3,14 @@
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_config::glob::FilePatterns;
|
use deno_config::glob::FilePatterns;
|
||||||
|
use deno_config::glob::PathOrPattern;
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
use ignore::overrides::OverrideBuilder;
|
||||||
|
use ignore::WalkBuilder;
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::fmt::Write as FmtWrite;
|
use std::fmt::Write as FmtWrite;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -46,27 +48,45 @@ pub fn create_gzipped_tarball(
|
||||||
|
|
||||||
let mut paths = HashSet::new();
|
let mut paths = HashSet::new();
|
||||||
|
|
||||||
let mut iterator = walkdir::WalkDir::new(dir).follow_links(false).into_iter();
|
let mut ob = OverrideBuilder::new(dir);
|
||||||
while let Some(entry) = iterator.next() {
|
ob.add("!.git")?.add("!node_modules")?.add("!.DS_Store")?;
|
||||||
|
|
||||||
|
for pattern in file_patterns.as_ref().iter().flat_map(|p| p.include.iter()) {
|
||||||
|
for path_or_pat in pattern.inner() {
|
||||||
|
match path_or_pat {
|
||||||
|
PathOrPattern::Path(p) => ob.add(p.to_str().unwrap())?,
|
||||||
|
PathOrPattern::Pattern(p) => ob.add(p.as_str())?,
|
||||||
|
PathOrPattern::RemoteUrl(_) => continue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let overrides = ob.build()?;
|
||||||
|
|
||||||
|
let iterator = WalkBuilder::new(dir)
|
||||||
|
.follow_links(false)
|
||||||
|
.require_git(false)
|
||||||
|
.git_ignore(true)
|
||||||
|
.git_global(true)
|
||||||
|
.git_exclude(true)
|
||||||
|
.overrides(overrides)
|
||||||
|
.filter_entry(move |entry| {
|
||||||
|
let matches_pattern = file_patterns
|
||||||
|
.as_ref()
|
||||||
|
.map(|p| p.matches_path(entry.path()))
|
||||||
|
.unwrap_or(true);
|
||||||
|
matches_pattern
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
for entry in iterator {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
|
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
let file_type = entry.file_type();
|
let Some(file_type) = entry.file_type() else {
|
||||||
|
// entry doesn’t have a file type if it corresponds to stdin.
|
||||||
let matches_pattern = file_patterns
|
|
||||||
.as_ref()
|
|
||||||
.map(|p| p.matches_path(path))
|
|
||||||
.unwrap_or(true);
|
|
||||||
if !matches_pattern
|
|
||||||
|| path.file_name() == Some(OsStr::new(".git"))
|
|
||||||
|| path.file_name() == Some(OsStr::new("node_modules"))
|
|
||||||
|| path.file_name() == Some(OsStr::new(".DS_Store"))
|
|
||||||
{
|
|
||||||
if file_type.is_dir() {
|
|
||||||
iterator.skip_current_dir();
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
};
|
||||||
|
|
||||||
let Ok(specifier) = Url::from_file_path(path) else {
|
let Ok(specifier) = Url::from_file_path(path) else {
|
||||||
diagnostics_collector
|
diagnostics_collector
|
||||||
|
|
|
@ -215,6 +215,43 @@ itest!(config_flag {
|
||||||
http_server: true,
|
http_server: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ignores_gitignore() {
|
||||||
|
let context = publish_context_builder().build();
|
||||||
|
let temp_dir = context.temp_dir().path();
|
||||||
|
temp_dir.join("deno.json").write_json(&json!({
|
||||||
|
"name": "@foo/bar",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"exports": "./main.ts"
|
||||||
|
}));
|
||||||
|
|
||||||
|
temp_dir.join("main.ts").write("import './sub_dir/b.ts';");
|
||||||
|
|
||||||
|
let gitignore = temp_dir.join(".gitignore");
|
||||||
|
gitignore.write("ignored.ts\nsub_dir/ignored.wasm");
|
||||||
|
|
||||||
|
let sub_dir = temp_dir.join("sub_dir");
|
||||||
|
sub_dir.create_dir_all();
|
||||||
|
sub_dir.join("ignored.wasm").write("");
|
||||||
|
sub_dir.join("b.ts").write("export default {}");
|
||||||
|
|
||||||
|
temp_dir.join("ignored.ts").write("");
|
||||||
|
|
||||||
|
let output = context
|
||||||
|
.new_command()
|
||||||
|
.arg("publish")
|
||||||
|
.arg("--dry-run")
|
||||||
|
.arg("--token")
|
||||||
|
.arg("sadfasdf")
|
||||||
|
.run();
|
||||||
|
output.assert_exit_code(0);
|
||||||
|
let output = output.combined_output();
|
||||||
|
assert_contains!(output, "b.ts");
|
||||||
|
assert_contains!(output, "main.ts");
|
||||||
|
assert_not_contains!(output, "ignored.ts");
|
||||||
|
assert_not_contains!(output, "ignored.wasm");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ignores_directories() {
|
fn ignores_directories() {
|
||||||
let context = publish_context_builder().build();
|
let context = publish_context_builder().build();
|
||||||
|
@ -260,6 +297,35 @@ fn ignores_directories() {
|
||||||
assert_not_contains!(output, "ignored.ts");
|
assert_not_contains!(output, "ignored.ts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn includes_directories_with_gitignore() {
|
||||||
|
let context = publish_context_builder().build();
|
||||||
|
let temp_dir = context.temp_dir().path();
|
||||||
|
temp_dir.join("deno.json").write_json(&json!({
|
||||||
|
"name": "@foo/bar",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"exports": "./main.ts",
|
||||||
|
"publish": {
|
||||||
|
"include": [ "deno.json", "main.ts" ]
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
temp_dir.join(".gitignore").write("main.ts");
|
||||||
|
temp_dir.join("main.ts").write("");
|
||||||
|
temp_dir.join("ignored.ts").write("");
|
||||||
|
|
||||||
|
let output = context
|
||||||
|
.new_command()
|
||||||
|
.arg("publish")
|
||||||
|
.arg("--token")
|
||||||
|
.arg("sadfasdf")
|
||||||
|
.run();
|
||||||
|
output.assert_exit_code(0);
|
||||||
|
let output = output.combined_output();
|
||||||
|
assert_contains!(output, "main.ts");
|
||||||
|
assert_not_contains!(output, "ignored.ts");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn includes_directories() {
|
fn includes_directories() {
|
||||||
let context = publish_context_builder().build();
|
let context = publish_context_builder().build();
|
||||||
|
@ -279,7 +345,6 @@ fn includes_directories() {
|
||||||
let output = context
|
let output = context
|
||||||
.new_command()
|
.new_command()
|
||||||
.arg("publish")
|
.arg("publish")
|
||||||
.arg("--log-level=debug")
|
|
||||||
.arg("--token")
|
.arg("--token")
|
||||||
.arg("sadfasdf")
|
.arg("sadfasdf")
|
||||||
.run();
|
.run();
|
||||||
|
|
Loading…
Reference in a new issue