mirror of
https://github.com/denoland/deno.git
synced 2024-12-23 23:59:59 -05:00
fix(publish): include explicitly specified .gitignored files and directories (#22790)
This allows explicitly overriding a .gitignore by specifying files and directories in "include". This does not apply to globs in an include as files matching those will still be gitignored. Additionally, individually gitignored files within an included directory will still be ignored.
This commit is contained in:
parent
2c6e9107b6
commit
40089b37c0
3 changed files with 69 additions and 7 deletions
|
@ -326,7 +326,30 @@ impl<TFilter: Fn(WalkEntry) -> bool> FileCollector<TFilter> {
|
|||
}
|
||||
|
||||
let mut maybe_git_ignores = if self.use_gitignore {
|
||||
Some(GitIgnoreTree::new(Arc::new(deno_runtime::deno_fs::RealFs)))
|
||||
// Override explicitly specified include paths in the
|
||||
// .gitignore file. This does not apply to globs because
|
||||
// that is way too complicated to reason about.
|
||||
let include_paths = file_patterns
|
||||
.include
|
||||
.as_ref()
|
||||
.map(|include| {
|
||||
include
|
||||
.inner()
|
||||
.iter()
|
||||
.filter_map(|path_or_pattern| {
|
||||
if let PathOrPattern::Path(p) = path_or_pattern {
|
||||
Some(p.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
Some(GitIgnoreTree::new(
|
||||
Arc::new(deno_runtime::deno_fs::RealFs),
|
||||
include_paths,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
@ -38,13 +38,19 @@ impl DirGitIgnores {
|
|||
pub struct GitIgnoreTree {
|
||||
fs: Arc<dyn deno_runtime::deno_fs::FileSystem>,
|
||||
ignores: HashMap<PathBuf, Option<Rc<DirGitIgnores>>>,
|
||||
include_paths: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl GitIgnoreTree {
|
||||
pub fn new(fs: Arc<dyn deno_runtime::deno_fs::FileSystem>) -> Self {
|
||||
pub fn new(
|
||||
fs: Arc<dyn deno_runtime::deno_fs::FileSystem>,
|
||||
// paths that should override what's in the gitignore
|
||||
include_paths: Vec<PathBuf>,
|
||||
) -> Self {
|
||||
Self {
|
||||
fs,
|
||||
ignores: Default::default(),
|
||||
include_paths,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,6 +100,16 @@ impl GitIgnoreTree {
|
|||
for line in text.lines() {
|
||||
builder.add_line(None, line).ok()?;
|
||||
}
|
||||
// override the gitignore contents to include these paths
|
||||
for path in &self.include_paths {
|
||||
if let Ok(suffix) = path.strip_prefix(dir_path) {
|
||||
let suffix = suffix.to_string_lossy().replace('\\', "/");
|
||||
let _ignore = builder.add_line(None, &format!("!/{}", suffix));
|
||||
if !suffix.ends_with('/') {
|
||||
let _ignore = builder.add_line(None, &format!("!/{}/", suffix));
|
||||
}
|
||||
}
|
||||
}
|
||||
let gitignore = builder.build().ok()?;
|
||||
Some(Rc::new(gitignore))
|
||||
});
|
||||
|
@ -122,7 +138,7 @@ mod test {
|
|||
"!file.txt\nignore.txt".into(),
|
||||
),
|
||||
]);
|
||||
let mut ignore_tree = GitIgnoreTree::new(Arc::new(fs));
|
||||
let mut ignore_tree = GitIgnoreTree::new(Arc::new(fs), Vec::new());
|
||||
let mut run_test = |path: &str, expected: bool| {
|
||||
let path = PathBuf::from(path);
|
||||
let gitignore = ignore_tree
|
||||
|
|
|
@ -409,7 +409,7 @@ fn ignores_directories() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn not_include_gitignored_file_even_if_matched_in_include() {
|
||||
fn not_include_gitignored_file_unless_exact_match_in_include() {
|
||||
let context = publish_context_builder().build();
|
||||
let temp_dir = context.temp_dir().path();
|
||||
temp_dir.join("deno.json").write_json(&json!({
|
||||
|
@ -417,22 +417,45 @@ fn not_include_gitignored_file_even_if_matched_in_include() {
|
|||
"version": "1.0.0",
|
||||
"exports": "./main.ts",
|
||||
"publish": {
|
||||
// won't match ignored because it needs to be
|
||||
// won't match ignored.ts because it needs to be
|
||||
// unexcluded via a negated glob in exclude
|
||||
"include": [ "deno.json", "*.ts" ]
|
||||
"include": [
|
||||
"deno.json",
|
||||
"*.ts",
|
||||
"exact_include.ts",
|
||||
"sub"
|
||||
]
|
||||
}
|
||||
}));
|
||||
|
||||
temp_dir.join(".gitignore").write("ignored.ts");
|
||||
temp_dir
|
||||
.join(".gitignore")
|
||||
.write("ignored.ts\nexact_include.ts\nsub/\nsub/ignored\n/sub_ignored\n");
|
||||
temp_dir.join("main.ts").write("");
|
||||
temp_dir.join("ignored.ts").write("");
|
||||
temp_dir.join("exact_include.ts").write("");
|
||||
let sub_dir = temp_dir.join("sub");
|
||||
sub_dir.create_dir_all();
|
||||
sub_dir.join("sub_included.ts").write("");
|
||||
sub_dir.join("ignored.ts").write(""); // this one is gitignored
|
||||
sub_dir.join("ignored").create_dir_all();
|
||||
sub_dir.join("ignored").join("ignored_also.ts").write("");
|
||||
let sub_ignored_dir = temp_dir.join("sub_ignored");
|
||||
sub_ignored_dir.create_dir_all();
|
||||
sub_ignored_dir.join("sub_ignored.ts").write("");
|
||||
|
||||
let output = context.new_command().arg("publish").arg("--dry-run").run();
|
||||
output.assert_exit_code(0);
|
||||
let output = output.combined_output();
|
||||
assert_contains!(output, "main.ts");
|
||||
// will match this exact match
|
||||
assert_contains!(output, "exact_include.ts");
|
||||
// will include this because the sub directory is included
|
||||
assert_contains!(output, "sub_included.ts");
|
||||
// it's gitignored
|
||||
assert_not_contains!(output, "ignored.ts");
|
||||
assert_not_contains!(output, "ignored_also.ts");
|
||||
assert_not_contains!(output, "sub_ignored.ts");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue