Skip to content

Commit

Permalink
fix(publish): include explicitly specified .gitignored files and dire…
Browse files Browse the repository at this point in the history
…ctories (#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.
  • Loading branch information
dsherret committed Mar 8, 2024
1 parent 2c6e910 commit 40089b3
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 7 deletions.
25 changes: 24 additions & 1 deletion cli/util/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down
20 changes: 18 additions & 2 deletions cli/util/gitignore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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))
});
Expand Down Expand Up @@ -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
Expand Down
31 changes: 27 additions & 4 deletions tests/integration/publish_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,30 +409,53 @@ 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!({
"name": "@foo/bar",
"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]
Expand Down

0 comments on commit 40089b3

Please sign in to comment.