summaryrefslogtreecommitdiff
path: root/cli/util/gitignore.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/util/gitignore.rs')
-rw-r--r--cli/util/gitignore.rs178
1 files changed, 0 insertions, 178 deletions
diff --git a/cli/util/gitignore.rs b/cli/util/gitignore.rs
deleted file mode 100644
index 4538e0912..000000000
--- a/cli/util/gitignore.rs
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use std::collections::HashMap;
-use std::path::Path;
-use std::path::PathBuf;
-use std::rc::Rc;
-use std::sync::Arc;
-
-/// Resolved gitignore for a directory.
-pub struct DirGitIgnores {
- current: Option<Rc<ignore::gitignore::Gitignore>>,
- parent: Option<Rc<DirGitIgnores>>,
-}
-
-impl DirGitIgnores {
- pub fn is_ignored(&self, path: &Path, is_dir: bool) -> bool {
- let mut is_ignored = false;
- if let Some(parent) = &self.parent {
- is_ignored = parent.is_ignored(path, is_dir);
- }
- if let Some(current) = &self.current {
- match current.matched(path, is_dir) {
- ignore::Match::None => {}
- ignore::Match::Ignore(_) => {
- is_ignored = true;
- }
- ignore::Match::Whitelist(_) => {
- is_ignored = false;
- }
- }
- }
- is_ignored
- }
-}
-
-/// Resolves gitignores in a directory tree taking into account
-/// ancestor gitignores that may be found in a directory.
-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>,
- // paths that should override what's in the gitignore
- include_paths: Vec<PathBuf>,
- ) -> Self {
- Self {
- fs,
- ignores: Default::default(),
- include_paths,
- }
- }
-
- pub fn get_resolved_git_ignore_for_dir(
- &mut self,
- dir_path: &Path,
- ) -> Option<Rc<DirGitIgnores>> {
- // for directories, provide itself in order to tell
- // if it should stop searching for gitignores because
- // maybe this dir_path is a .git directory
- let parent = dir_path.parent()?;
- self.get_resolved_git_ignore_inner(parent, Some(dir_path))
- }
-
- pub fn get_resolved_git_ignore_for_file(
- &mut self,
- file_path: &Path,
- ) -> Option<Rc<DirGitIgnores>> {
- let dir_path = file_path.parent()?;
- self.get_resolved_git_ignore_inner(dir_path, None)
- }
-
- fn get_resolved_git_ignore_inner(
- &mut self,
- dir_path: &Path,
- maybe_parent: Option<&Path>,
- ) -> Option<Rc<DirGitIgnores>> {
- let maybe_resolved = self.ignores.get(dir_path).cloned();
- if let Some(resolved) = maybe_resolved {
- resolved
- } else {
- let resolved = self.resolve_gitignore_in_dir(dir_path, maybe_parent);
- self.ignores.insert(dir_path.to_owned(), resolved.clone());
- resolved
- }
- }
-
- fn resolve_gitignore_in_dir(
- &mut self,
- dir_path: &Path,
- maybe_parent: Option<&Path>,
- ) -> Option<Rc<DirGitIgnores>> {
- if let Some(parent) = maybe_parent {
- // stop searching if the parent dir had a .git directory in it
- if self.fs.exists_sync(&parent.join(".git")) {
- return None;
- }
- }
-
- let parent = dir_path.parent().and_then(|parent| {
- self.get_resolved_git_ignore_inner(parent, Some(dir_path))
- });
- let current = self
- .fs
- .read_text_file_lossy_sync(&dir_path.join(".gitignore"), None)
- .ok()
- .and_then(|text| {
- let mut builder = ignore::gitignore::GitignoreBuilder::new(dir_path);
- 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))
- });
- if parent.is_none() && current.is_none() {
- None
- } else {
- Some(Rc::new(DirGitIgnores { current, parent }))
- }
- }
-}
-
-#[cfg(test)]
-mod test {
- use deno_runtime::deno_fs::InMemoryFs;
-
- use super::*;
-
- #[test]
- fn git_ignore_tree() {
- let fs = InMemoryFs::default();
- fs.setup_text_files(vec![
- ("/.gitignore".into(), "file.txt".into()),
- ("/sub_dir/.gitignore".into(), "data.txt".into()),
- (
- "/sub_dir/sub_dir/.gitignore".into(),
- "!file.txt\nignore.txt".into(),
- ),
- ]);
- 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.get_resolved_git_ignore_for_file(&path).unwrap();
- assert_eq!(
- gitignore.is_ignored(&path, /* is_dir */ false),
- expected,
- "Path: {}",
- path.display()
- );
- };
- run_test("/file.txt", true);
- run_test("/other.txt", false);
- run_test("/data.txt", false);
- run_test("/sub_dir/file.txt", true);
- run_test("/sub_dir/other.txt", false);
- run_test("/sub_dir/data.txt", true);
- run_test("/sub_dir/sub_dir/file.txt", false); // unignored up here
- run_test("/sub_dir/sub_dir/sub_dir/file.txt", false);
- run_test("/sub_dir/sub_dir/sub_dir/ignore.txt", true);
- run_test("/sub_dir/sub_dir/ignore.txt", true);
- run_test("/sub_dir/ignore.txt", false);
- run_test("/ignore.txt", false);
- }
-}